How to avoid deadlocks in parallel named pipes?
I’m working on a flow-based programming system called net2sh It is currently based on shell tools that connect via named pipes. Multiple processes work together to get work done, communicating through named pipes, not unlike a production line in a factory.
Overall, it works well, but there is one major problem. In cases where processes communicate through two or more named pipes, the Send process and the Receive process must open the pipes in the same order. This is because when a process opens a named pipe, it blocks until the other end is also opened.
I would like a way to avoid this without generating additional “helper” processes for each pipeline, cracking existing components, and disrupting the program network to avoid this issue.
Ideally, I’m looking for some “non-blocking fifo” option where “open” on the FIFO always succeeds immediately, but if the pipe buffer is full (or empty, for reading), subsequent operations may block… I’d even consider using a kernel patch for this. According to fifo(7) O_NONBLOCK did do something different when opening fifos, which wasn’t what I wanted, and in order to use it I had to rewrite every existing shell tool like cat.
This is a minimal example of a deadlock:
mkfifo a b
(> a; > b; ) &
(< b; < a; ) &
wait
I would appreciate it if you could help me solve this problem wisely!
Solution
Here’s a good description of using O_NONBLOCK
and named pipes: How do I perform a non-blocking fopen on a named pipe (mkfifo)?
It sounds like you want it to work throughout your environment without changing any C code. Therefore, one approach is to set up LD_PRELOAD
to some shared library that contains an open(2)
wrapper that adds O_NONBLOCK
to flags
whenever pathname
references a named pipe.
A
concise example of overriding a library function using LD_PRELOAD
is as follows: https://www.technovelty.org/c/using-ld_preload-to-override-a-function.html
Whether this really works in practice without breaking anything else, you’ll have to figure it out yourself (please let us know!).