static int setup_pipes (signal_info** signals, int count, struct pollfd *fd_structs, int *currfd) { int i; int r = 0; for (i = 0; i < count; ++i) { signal_info* h; int filedes[2]; h = signals [i]; if (mph_int_get (&h->pipecnt) == 0) { if ((r = pipe (filedes)) != 0) { break; } h->read_fd = filedes [0]; h->write_fd = filedes [1]; } mph_int_inc (&h->pipecnt); fd_structs[*currfd].fd = h->read_fd; fd_structs[*currfd].events = POLLIN; ++(*currfd); } return r; }
// This handler is registered once for each UnixSignal object. A pipe is maintained // for each one; Wait users read at one end of this pipe, and default_handler sends // a write on the pipe for each signal received while the Wait is ongoing. // // Notice a fairly unlikely race condition exists here: Because we synchronize with // pipe teardown, but not install/uninstall (in other words, we are only trying to // protect against writing on a closed pipe) it is technically possible a full // uninstall and then an install could complete after signum is checked but before // the remaining instructions execute. In this unlikely case count could be // incremented or a byte written on the wrong signal handler. static void default_handler (int signum) { int i; for (i = 0; i < NUM_SIGNALS; ++i) { int fd; signal_info* h = &signals [i]; if (mph_int_get (&h->signum) != signum) continue; mph_int_inc (&h->count); if (!acquire_pipelock_handler (&h->pipelock)) continue; // Teardown is occurring on this object, no one to send to. fd = mph_int_get (&h->write_fd); if (fd > 0) { // If any listener exists to write to int j,pipecounter; char c = signum; // (Value is meaningless) pipecounter = mph_int_get (&h->pipecnt); // Write one byte per pipe listener for (j = 0; j < pipecounter; ++j) { int r; do { r = write (fd, &c, 1); } while (keep_trying (r)); } } release_pipelock_handler (&h->pipelock); } }
// Set up a signal_info to begin waiting for signal static int setup_pipes (signal_info** signals, int count, struct pollfd *fd_structs, int *currfd) { int i; int r = 0; for (i = 0; i < count; ++i) { signal_info* h; int filedes[2]; h = signals [i]; if (mph_int_get (&h->pipecnt) == 0) { // First listener for this signal_info if ((r = pipe (filedes)) != 0) { break; } mph_int_set (&h->read_fd, filedes [0]); mph_int_set (&h->write_fd, filedes [1]); } mph_int_inc (&h->pipecnt); fd_structs[*currfd].fd = mph_int_get (&h->read_fd); fd_structs[*currfd].events = POLLIN; ++(*currfd); // count is verified less than NUM_SIGNALS by caller } return r; }
static void default_handler (int signum) { int i; for (i = 0; i < NUM_SIGNALS; ++i) { int fd; signal_info* h = &signals [i]; if (mph_int_get (&h->signum) != signum) continue; mph_int_inc (&h->count); fd = mph_int_get (&h->write_fd); if (fd > 0) { int j,pipecounter; char c = signum; pipecounter = mph_int_get (&h->pipecnt); for (j = 0; j < pipecounter; ++j) { int r; do { r = write (fd, &c, 1); } while (keep_trying (r)); } } } }