[Bug 3547] shell read is maybe too safe
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".
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.
Create a pipe p, trap SIGINT with a "write(p, &c, 1)" handler,
and loop over a poll() on stdin and p (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 will be readable, you will
know you got a SIGINT, and can handle it in a normal (i.e.
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. :)
More information about the busybox