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.

5
  • Other than a FIFO with no writer? Commented Feb 18, 2018 at 19:08
  • Heh, sorry, just clarified why I was hoping for a solution besides a FIFO. (I want to avoid the need to clean the FIFO up.)
    – benesch
    Commented Feb 18, 2018 at 19:10
  • This sounds like a XY-Problem. What do you want to achieve by this?
    – Stefan M
    Commented Feb 18, 2018 at 19:11
  • @Stefan M, I added context to the original question. You’re right in that I have a solution that solves my original problem, but I’m still interested in whether a forever-blocking special device exists out of sheer curiosity.
    – benesch
    Commented Feb 18, 2018 at 19:20
  • 1
    As for unlinking the FIFO, you can unlink it directly, and it will be cleaned up when netcat no longer has an open filehandle for it. Commented Feb 18, 2018 at 19:24

2 Answers 2

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).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .