3

I’m looking for a variant of /dev/null that causes read to block forever, rather than returning EOF immediately. Does such a device exist?

I could probably create a named pipe (via mkfifo) to achieve the desired effect, but I’d rather not have to deal with unlinking the FIFO at the end of the script.

For context, I want to wait for an RPC server to quit. To avoid polling, I open a connection via netcat:

netcat localhost 12345

The connection will be closed automatically when the server closes. Unfortunately, when running the command via SSH, stdin is set to /dev/null and so netcat exits immediately after sending EOF instead of waiting for the connection to close. netcat -d (don’t wait for stdin) has a bug? on macOS and spins hot, meaning the solution is actually worse than polling at a reasonable interval.

I have a solution to this problem—hooking stdin up to a pipe—but I am specifically interested in the question as stated out of pure curiosity.

benesch
  • 131

2 Answers2

2

Unfortunately, when running the command via SSH, stdin is set to /dev/null and so netcat exits immediately after sending EOF instead of waiting for the connection to close.

In bash version 4 one can create a co-process doing read, connected via pipes to the parent process, and read from its always open but empty stdout. This method requires no clean-up.

Example:

coproc read # Never writes anything into its stdout.
netcat localhost 12345 <&${COPROC[0]} # Read from co-process' stdout.

Another way is to pipe stdin from stdout of a long sleep:

sleep 365d | netcat localhost 12345
0

You can create one with cryptsetup (or, I guess, dmsetup works too).

# truncate -s 8M luksblock.img
# cryptsetup luksFormat luksblock.img
# cryptsetup luksOpen luksblock.img luksblock
# cryptsetup luksSuspend luksblock
# cat /dev/mapper/luksblock
( ... no output because it's blocked / suspended ... )

What it looks like in dmsetup:

# dmsetup info luksblock
Name:              luksblock
State:             SUSPENDED
Read Ahead:        256
Tables present:    LIVE
Open count:        0
Event number:      0
Major, minor:      253, 71
Number of targets: 1
UUID: CRYPT-LUKS1-87bc6d9fd7fa419bbf15425c062d0916-luksblock

You can use dmsetup to suspend a device:

dmsetup suspend luksblock

So it should be possible to create a suspended device mapping that does not need to be backed by a luksblock.img file in the first place, but I will leave that final bit to you. :-P


Of course this approach has a major downside. This device will be listed among all the other block devices in /proc/partitions, and everything that monitors or detects devices (like LVM looking for new physical volumes) will try to read and get stuck on the block as well. This will stop devices from being detected (because the processes doing so are stuck) and the machine might no longer reboot either (because the processes handling shutdown procedures are stuck).

frostschutz
  • 48,978