I am trying to receive a signal when I/O is possible on a file descriptor. The program needs to be doing something else when it is not doing I/O, so using select(2) is not
Ah, interesting.
The short answer is, a SIGIO is repeatedly arriving for stdin because stdin is writeable, and, separately, your SIGIO delivery is not quite properly set up.
Why is si_fd apparently unreliable?
First, you need to specify SA_SIGINFO in sa_flags
before you can safely use an sa_sigaction
handler.
Second, you need to #define _GNU_SOURCE
and explicitly F_SETSIG to SIGIO before Linux will fill in si_fd
(and si_band
, for that matter) for you. A bit silly, IMHO, but so it is. Without this, the value passed in to si_fd
is not meaningful, as you discovered.
Why is SIGIO being delivered over and over?
I'm guessing your program's stdin is inherited from your invoking shell, which I'd guess is a terminal device and is writeable. Just as fd 0 would continuously select(2) writeable, so will it continuously generate SIGIOs for you.
In any case, si_band
holds the answer. Enable F_SETSIG, #include <poll.h>
, and inspect si_band
for POLLIN, POLLOUT, etc., to determine which I/O events tripped the signal.
Really, stdin is writeable?
Yeah. Try these for comparison:
$ [ -w /dev/stdin ] && echo Yes, stdin is writeable
Yes, stdin is writeable
# Endless SIGIOs
$ ./my-sigio-prog
^C
# No SIGIO
$ ./my-sigio-prog < /dev/null
# Two SIGIOs, after a delay. One for line-buffered "foo\n" and one for EOF
$ { sleep 3; echo foo; sleep 3; } | ./my-sigio-prog