6

I went through examples and man page but couldn't figure out difference between signalfd and sigwaitinfo Apart from syntax both are doing same thing i.e. waiting for signal storing it details into some structure.

in man page it is written. This provides an alternative to the use of a signal handler or sigwaitinfo(2), and has the advantage that the file descriptor may be monitored by select(2), poll(2), and epoll(7).

Can anyone please explain me what does it exactly means?

Suri
  • 391
  • 2
  • 4
  • 9

2 Answers2

11

The select(2), poll(2), and epoll(7) system calls are just a way to wait for events on file descriptors (small integers representing an I/O channel). Events can include "data read for read", "ready to write", things like that. Your code makes up a set of file descriptors that will eventually have an event, and then calls select(), or poll() or epoll() to cause the program to wait until data arrives, the kernel connects the socket to some other host, a descriptor had an error, whatever.

signalfd(2) adds a new event: a signal has arrived. In unix/linux/*BSD a "signal" is a more-or-less asynchronous event: CPU tried to execute an illegal instruction, I/O is ready, code divided by zero, the modem hung up. signalfd(2) lets you create a file descriptor, usable in select(), poll(), epoll(), that has an event when a signal arrives.

In the past, you would specify a handler function, which the kernel magically called when a signal arrives (a.k.a. an "upcall"). If you used the sigaction() system call to tell the kernel what function you wanted it to call, you got the same information that sigwaitinfo() can get you.

The difference between setting a handler function with signal() or sigaction() over signalfd() is that the handler function could get magically called at any time: parts of your code had to be re-entrant (not just thread-safe, mind you) to deal with the "at any time" nature of signals. With signalfd(), a signal is just another event to deal with in your code's event loop. Your code just executes as usual.

sigwaitinfo() causes your code to pause until and when a signal you specified arrives. Your code does nothing until that signal arrives. No event loop, no nothing. It also looks like sigwaitinfo() is part of the real time stuff in the Linux kernel. sigwaitinfo() could be thought of as designating a spot in the code for the kernel to call when a signal arrives, rather than designating a function to call.

Addition:

I've just discovered a blog post sbout the "self pipe trick". Apparently not only is it inconvenient code-wise to handle signals and select-based I/O, you can also suffer "nasty race conditions". The self pipe trick gets around that by doing essentially what signalfd(2) does, but all in user space, and at a cost of more code.

  • 1
    FYI for anyone who might refer to this in the future: sigwait() and sigwaitinfo() are intended to be used with threads -- indeed a dedicated thread for all signal handling should use one of these calls to "receive" asynchronous signals and then pass on any information to other thread(s) in a manner that makes sense for the other thread(s), perhaps using pthread_cond_signal() or pthread_cond_broadcast(), or by injecting events into whatever message queue is used by the main event handling thread, etc. – Greg A. Woods Oct 18 '15 at 19:52
  • Link broken. :( – Harith Feb 10 '23 at 13:20
0

Shortly: When you use sigwaitinfo() you can wait for signals only. When you use signalfd() combined with poll/select/etc you can wait for any event that can be accessed via file descriptor (file IO, timerfd, eventfd, etc.).

Dmitry
  • 11