Self-pipe trick (and failings)
Posted Mar 30, 2006 22:13 UTC (Thu) by
mkerrisk (subscriber, #1978)
In reply to:
Self-pipe trick (and failings) by jreiser
Parent article:
The new pselect() system call
John,
The fourth paragraph of the article begins, "The traditional solution to this problem is the so-called self-pipe trick ...". That paragraph alleges non-obvious defects in such a trick. What is your response?
I'm not sure if you are asking this question of me (author of article) or "mtk77" (who your article seems to reply to). Anyway, I don't allege any defects in the self-pipe trick; all I say is that it requires quite a bit of code to do things right:
-
We create a pipe, and use fcntl(F_SETFL) to mark both ends non-blocking (O_NONBLOCK).
-
We include the read end of the pipe in the readfds set given to select().
-
When the signal handler is called, it writes a byte to the pipe. By making the write end of the pipe non-blocking, we avoid the possibility of blocking in the signal handler if signals are delivered so rapidly that the pipe fills up. (If we fail to write a byte to the pipe because it is full, that doesn't matter: the presence of the existing bytes already informs us that the signal has been delivered.)
-
We place the select() call in a loop and restart it if interrupted by a signal:
while ((ready = select(nfds, &readfds, NULL, NULL, NULL)) == -1 &
errno == EINTR)
continue;
- After the select() we can determine if the signal arrived by checking whether the read end of the pipe is among the descriptors returned in readfds.
- We read all of the bytes from the pipe (so that we can know when new signals occur), and take whatever action is needed in response to the signal.
It all works fine, but
pselect() allows us to achieve the same result with less code.
(
Log in to post comments)