User: Password:
|
|
Subscribe / Log in / New account

The new pselect() system call

The new pselect() system call

Posted Mar 30, 2006 16:35 UTC (Thu) by mtk77 (guest, #6040)
Parent article: The new pselect() system call

The traditional way to deal with this is for the process to create a pipe and the select call to include that in its list. Then, the signal handler just writes a byte down the pipe.

My little inetd at http://hairy.beasts.org/whinetd/whinetd/src/whinetd.c uses this technique.


(Log in to post comments)

Self-pipe trick (and failings)

Posted Mar 30, 2006 21:03 UTC (Thu) by jreiser (subscriber, #11027) [Link]

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?

Self-pipe trick (and failings)

Posted Mar 30, 2006 22:13 UTC (Thu) by mkerrisk (subscriber, #1978) [Link]

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:
  1. We create a pipe, and use fcntl(F_SETFL) to mark both ends non-blocking (O_NONBLOCK).
  2. We include the read end of the pipe in the readfds set given to select().
  3. 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.)
  4. 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;
    
  5. 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.
  6. 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.

Self-pipe trick (and failings)

Posted Mar 31, 2006 1:21 UTC (Fri) by dougm (guest, #4615) [Link]

Just a nit: I think you want '&&' in the while condition, not '&'.

Self-pipe trick (and failings)

Posted Mar 31, 2006 3:41 UTC (Fri) by mkerrisk (subscriber, #1978) [Link]

Just a nit: I think you want '&&' in the while condition, not '&'.

Doh! Thanks, yes.

Self-pipe trick (and failings)

Posted Mar 31, 2006 13:43 UTC (Fri) by clugstj (subscriber, #4020) [Link]

Yes, it takes some code, but it only needs to be written and debugged once. Then tuck it into you comm library behind a simple interface and forget about the gory details. This is a problem that can be solved completely in user space. Adding a new system call to handle it is adding complexity to the kernel for no good reason.

It is not a better solution just because it takes less code (in user space).

Self-pipe trick (and failings)

Posted Apr 6, 2006 10:09 UTC (Thu) by renox (subscriber, #23785) [Link]

> Yes, it takes some code, but it only needs to be written and debugged once.

Well does glibc includes it?
No because the self-pipe trick cannot really be put into a library: it play tricks with signals, pipes which could have impact in your code, so each userspace program which need it must reimplement it, I'd hardly call this 'once'.

Whereas kernel implementation is really unique, so it is really better.
Plus it is conforming to POSIX standard, even better!

That said I find quite awful that glibc would implement pselect leaving the unsuspecting developer vulnerable to the race condition, it should be either implemented in the kernel or not at all (unless the library find a way to close the race condition of course).


Copyright © 2017, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds