[Bug 3547] shell read is maybe too safe

Laurent Bercot ska-dietlibc at skarnet.org
Mon May 9 09:19:14 UTC 2011


> Although I think the fix revealed a deepere problem:
> hush's way of handling signals isn't good for read
> and for reading commands from stdin: since we block
> signals we are interested in, we cannot detect them
> while we wait for input on a fd.

 Ew. I sense some mass rewriting ahead.


> Changing signal handling to a different scheme,
> where they are caught and recorded, will somewhat help,
> because now poll/read syscalls will be interruptible,
> but this creates another problem: many other sycalls
> may start failing with EINTR too, and we don't check
> for that. The problem is, EINTR case happens rarely.
> IOW: we may have many rarely-triggered bugs, one
> per every syscall we don't wrap with "repeat on EINTR"
> code, or with "if we got EINTR, propagate EINTR".

 Indeed.
 http://www.skarnet.org/tmp/doc/libstddjb/safewrappers.html
 (non-permanent URL)
 Safe wrappers should be used everywhere, *even* when SIGINT is
meant to be detected: the handling part must be done in another
place than the chunk of code containing your interrupted system
call. See below.


> Ideas anyone?

 As always when you need to mix signals and I/O: use a self-pipe.
 http://www.skarnet.org/tmp/doc/libstddjb/selfpipe.html
 (non-permanent URL)
 and http://cr.yp.to/docs/selfpipe.html

 Create a pipe p, trap SIGINT with a "write(p[1], &c, 1)" handler,
and loop over a poll() on stdin and p[0] (and maybe other stuff you need).
 Use safe wrappers for your (asynchronous) reads and your (preferably
asynchronous, but it doesn't really matter) writes.
 When you get a SIGINT, it will be momentarily ignored if you're in the
middle of performing some operation ; but there will be a byte in p, and
as soon as you come back to the poll(), p[0] will be readable, you will
know you got a SIGINT, and can handle it in a normal (i.e.
non-interrupt-handler) context.

 The self-pipe trick is the ultimate solution to mixing I/O and signals,
because it integrates signal handling into the generic select/poll
asynchronous I/O event framework. There is no case it cannot handle.
Teaching it should be a mandatory part of every Unix course. :)

-- 
 Laurent


More information about the busybox mailing list