As suggested by Julie Pelletier, I'm making this answer about the workaround we found in our discussion.
You cannot easily identify deadlocked situations as described in my question, but you can pre-emptively vent the named pipe as a workaround before anyone deletes it (if you really cannot avoid such a deletion, as in my case). This venting should allow any writer currently blocked trying to open the pipe, to succeed with the open operation but fail during the actual write operation (-> broken pipe). Failing might be better than a deadlock. In order to not immediately run into the next deadlock, you should move the pipe before venting it, and delete it afterwards.
# rename the pipe, i.e. move it out of the way
mv -f /tmp/test.pipe /tmp/test.pipe~ 2>/dev/null
# vent the pipe, i.e. shortly open it for reading but don't read from it.
# call the subshell dd and empty echo calls in the background to avoid
# deadlocking on redundant venting.
(dd if=/tmp/test.pipe~ count=0 2>/dev/null & echo -n "" >/tmp/test.pipe~ &)
# delete the old pipe
rm -f /tmp/test.pipe~
If you know which program executes the faulty deletion, you might want to wrap that program into a small script, that does the venting and forgoes the deletion.
It could be used as such, but it sucks.
For example, dd bs=1M
would be a 1 MiB buffer, however it might not solve your audio problem. If dd
gets a short read, it will pass that along directly, so it won't use the buffer as such. You can add iflag=fullblock
to force dd
filling up its buffer entirely, but then it would read 1 MiB of data, write 1 MiB of data, read 1 MiB of data, ... dd
won't accept new input before the output step is done, so your "buffer" would be 100% full, 100% empty, 100% full... and for however long it takes the buffer to fill up / empty out, the other side will be stuck.
This is not a characteristic you want/expect when thinking of pipe buffers. If you look at actual pipe buffers such as bfr
or pv
, they all accept new input while output is going on, they strive to maintain a good fill rate throughout so neither side has to wait more than absolutely necessary.
With a real pipe buffer, input will always be accepted (while the buffer is not full) and output will always be provided (while the buffer is not empty) and they might have advanced options such as guaranteeing a prefill, min-fill, ...
dd
doesn't do any of that, in fact dd
relies on buffering being done on the outside, when working with block devices, read/write concurrency is largely provided by the kernel (readahead/cache/...).
Basically you'd only consider dd
as a pipe buffer in minimalistic environments that have no other programs suited to the task available.
If you must use dd
but the characteristics of dd
are not suited to your task, you could daisy chain multiple dd
to get a "smoother" result of a buffer. But even then it might not be suitable for some use cases.
Best Answer
The capacity of a pipe buffer varies across systems (and can even vary on the same system). I am not sure there is a quick, easy, and cross platform way to just lookup the capacity of a pipe.
Mac OS X, for example, uses a capacity of 16384 bytes by default, but can switch to 65336 byte capacities if large write are made to the pipe, or will switch to a capacity of a single system page if too much kernel memory is already being used by pipe buffers (see
xnu/bsd/sys/pipe.h
, andxnu/bsd/kern/sys_pipe.c
; since these are from FreeBSD, the same behavior may happen there, too).One Linux pipe(7) man page says that pipe capacity is 65536 bytes since Linux 2.6.11 and a single system page prior to that (e.g. 4096 bytes on (32-bit) x86 systems). The code (
include/linux/pipe_fs_i.h
, andfs/pipe.c
) seems to use 16 system pages (i.e. 64 KiB if a system page is 4 KiB), but the buffer for each pipe can be adjusted via a fcntl on the pipe (up to a maximum capacity which defaults to 1048576 bytes, but can be changed via/proc/sys/fs/pipe-max-size
)).Here is a little bash/perl combination that I used to test the pipe capacity on my system:
Here is what I found running it with various write sizes on a Mac OS X 10.6.7 system (note the change for writes larger than 16KiB):
The same script on Linux 3.19:
Note: The
PIPE_BUF
value defined in the C header files (and the pathconf value for_PC_PIPE_BUF
), does not specify the capacity of pipes, but the maximum number of bytes that can be written atomically (see POSIX write(2)).Quote from
include/linux/pipe_fs_i.h
: