2

I want to use named pipes as asynchrnonous task queues (JMS-like, perhaps).

For example, suppose a client sends some data that I wish to insert into a database, but I want the client to disconnect from the server immediately and the server process pipe the data into a named pipe. Then completely independently read the data from the pipe and perform a SQL insert, which might be very slow - but the client doesn't notice because it gets a response immediately.

As a prototype, I thought this would work (for simplicity the "45" is echoed rather than sent through a netcat client-server pair):

zsh> nohup echo "45" > my_named_pipe &
zsh> exit
zsh: warning: 1 jobs SIGHUPed

Then much later, execute

zsh> cat my_named_pipe

But nothing comes out of the pipe. What's wrong with my setup?

PS: I've never got nohup to work. I always rely on disown which I don't want to do as a separate command in this scenario.

Sridhar Sarnobat
  • 1,802
  • 20
  • 27
  • I can't reproduce this. What version of bash do you have? –  Nov 20 '14 at 21:17
  • I'm actually using zsh 5.0.2 (though I wrote "bash" above). What happens when you do it? What version of bash do you use? If it works for you I should try that out myself. – Sridhar Sarnobat Nov 20 '14 at 21:46
  • Oh, it works for me with bash. So zsh is to blame? – Sridhar Sarnobat Nov 20 '14 at 21:57
  • I'd say bash is to blame for not cleaning up its children when it gets a SIGHUP but if you want to look at it another way I can't stop you –  Nov 20 '14 at 22:00

2 Answers2

3

When you do:

nohup echo "45" > my_named_pipe &

The shell forks itself. In the child, it opens my_named_pipe for writing. That open() blocks until something else opens my_named_pipe for reading.

When you run exit in the parent process, the child is still blocked on the open() and has not executed nohup yet.

So upon exiting you shell, the shell sends SIGHUP to the child, which it doesn't ignore since it has not run nohup yet.

Just run:

(echo 45 > my_named_pipe &)

Or with zsh:

echo 45 > my_named_pipe &!

&! is zsh syntactic sugar for disown

Both BASH and ZSH have a nice builtin called disown. It enables user to detach process from the shell in a way much similar to that of nohup. ZSH has a nice sugar for it: you can put &! at the end of the command, and it would be detached. BASH doesn’t have such sugar

http://blog.debiania.in.ua/posts/2013-03-13-fun-with-bash-disown.html

Sridhar Sarnobat
  • 1,802
  • 20
  • 27
2

The problem you're having, and the reason it's shell-dependent, is that the > redirection is processed first, and if nobody is reading the pipe yet, it will block. Only after the open succeeds will the shell execute nohup. You disconnected while it was still blocked in open, so nohup hadn't happened yet and the SIGHUP killed the background process. This is why disown is better. It applies to the job immediately.

From my attempt at reproducing the problem with bash, it seems that bash doesn't relay the session-ending SIGHUP to its children like zsh does, so the background job survives.