Print this page
8634 epoll fails to wake on certain edge-triggered conditions
8635 epoll should not emit POLLNVAL
8636 recursive epoll should emit EPOLLRDNORM
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Igor Kozhukhov <igor@dilos.org>
   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2016 Joyent, Inc.
  14  */
  15 
  16 /*
  17  * Support for the signalfd facility, a Linux-borne facility for
  18  * file descriptor-based synchronous signal consumption.
  19  *
  20  * As described on the signalfd(3C) man page, the general idea behind these
  21  * file descriptors is that they can be used to synchronously consume signals
  22  * via the read(2) syscall.  While that capability already exists with the
  23  * sigwaitinfo(3C) function, signalfd holds an advantage since it is file
  24  * descriptor based: It is able use the event facilities (poll(2), /dev/poll,
  25  * event ports) to notify interested parties when consumable signals arrive.
  26  *
  27  * The signalfd lifecycle begins When a process opens /dev/signalfd.  A minor
  28  * will be allocated for them along with an associated signalfd_state_t struct.
  29  * It is there where the mask of desired signals resides.
  30  *
  31  * Reading from the signalfd is straightforward and mimics the kernel behavior
  32  * for sigtimedwait().  Signals continue to live on either the proc's p_sig, or
  33  * thread's t_sig, member.  During a read operation, those which match the mask


 543                 res = 0;
 544 
 545         return (res);
 546 }
 547 
 548 /*
 549  * If ksigset_t's were a single word, we would do:
 550  *      return (((p->p_sig | t->t_sig) & set) & fillset);
 551  */
 552 static int
 553 signalfd_sig_pending(proc_t *p, kthread_t *t, k_sigset_t set)
 554 {
 555         return (((p->p_sig.__sigbits[0] | t->t_sig.__sigbits[0]) &
 556             set.__sigbits[0]) |
 557             ((p->p_sig.__sigbits[1] | t->t_sig.__sigbits[1]) &
 558             set.__sigbits[1]) |
 559             (((p->p_sig.__sigbits[2] | t->t_sig.__sigbits[2]) &
 560             set.__sigbits[2]) & FILLSET2));
 561 }
 562 
 563 _NOTE(ARGSUSED(4))
 564 static int
 565 signalfd_poll(dev_t dev, short events, int anyyet, short *reventsp,
 566     struct pollhead **phpp)
 567 {
 568         signalfd_state_t *state, **sstate;
 569         minor_t minor = getminor(dev);
 570         kthread_t *t = curthread;
 571         proc_t *p = ttoproc(t);
 572         short revents = 0;
 573 
 574         sstate = ddi_get_soft_state(signalfd_softstate, minor);
 575         state = *sstate;
 576 
 577         mutex_enter(&state->sfd_lock);
 578 
 579         if (signalfd_sig_pending(p, t, state->sfd_set) != 0)
 580                 revents |= POLLRDNORM | POLLIN;
 581 
 582         mutex_exit(&state->sfd_lock);
 583 
 584         if (!(*reventsp = revents & events) && !anyyet) {

 585                 sigfd_proc_state_t *pstate;
 586                 sigfd_poll_waiter_t *pw;
 587 
 588                 /*
 589                  * Enable pollwakeup handling.
 590                  */
 591                 mutex_enter(&p->p_lock);
 592                 if ((pstate = (sigfd_proc_state_t *)p->p_sigfd) == NULL) {
 593 
 594                         mutex_exit(&p->p_lock);
 595                         pstate = kmem_zalloc(sizeof (*pstate), KM_SLEEP);
 596                         list_create(&pstate->sigfd_list,
 597                             sizeof (sigfd_poll_waiter_t),
 598                             offsetof(sigfd_poll_waiter_t, spw_list));
 599                         pstate->sigfd_pollwake_cb = signalfd_pollwake_cb;
 600 
 601                         /* Check again, after blocking for the alloc. */
 602                         mutex_enter(&p->p_lock);
 603                         if (p->p_sigfd == NULL) {
 604                                 p->p_sigfd = pstate;


   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2017 Joyent, Inc.
  14  */
  15 
  16 /*
  17  * Support for the signalfd facility, a Linux-borne facility for
  18  * file descriptor-based synchronous signal consumption.
  19  *
  20  * As described on the signalfd(3C) man page, the general idea behind these
  21  * file descriptors is that they can be used to synchronously consume signals
  22  * via the read(2) syscall.  While that capability already exists with the
  23  * sigwaitinfo(3C) function, signalfd holds an advantage since it is file
  24  * descriptor based: It is able use the event facilities (poll(2), /dev/poll,
  25  * event ports) to notify interested parties when consumable signals arrive.
  26  *
  27  * The signalfd lifecycle begins When a process opens /dev/signalfd.  A minor
  28  * will be allocated for them along with an associated signalfd_state_t struct.
  29  * It is there where the mask of desired signals resides.
  30  *
  31  * Reading from the signalfd is straightforward and mimics the kernel behavior
  32  * for sigtimedwait().  Signals continue to live on either the proc's p_sig, or
  33  * thread's t_sig, member.  During a read operation, those which match the mask


 543                 res = 0;
 544 
 545         return (res);
 546 }
 547 
 548 /*
 549  * If ksigset_t's were a single word, we would do:
 550  *      return (((p->p_sig | t->t_sig) & set) & fillset);
 551  */
 552 static int
 553 signalfd_sig_pending(proc_t *p, kthread_t *t, k_sigset_t set)
 554 {
 555         return (((p->p_sig.__sigbits[0] | t->t_sig.__sigbits[0]) &
 556             set.__sigbits[0]) |
 557             ((p->p_sig.__sigbits[1] | t->t_sig.__sigbits[1]) &
 558             set.__sigbits[1]) |
 559             (((p->p_sig.__sigbits[2] | t->t_sig.__sigbits[2]) &
 560             set.__sigbits[2]) & FILLSET2));
 561 }
 562 

 563 static int
 564 signalfd_poll(dev_t dev, short events, int anyyet, short *reventsp,
 565     struct pollhead **phpp)
 566 {
 567         signalfd_state_t *state, **sstate;
 568         minor_t minor = getminor(dev);
 569         kthread_t *t = curthread;
 570         proc_t *p = ttoproc(t);
 571         short revents = 0;
 572 
 573         sstate = ddi_get_soft_state(signalfd_softstate, minor);
 574         state = *sstate;
 575 
 576         mutex_enter(&state->sfd_lock);
 577 
 578         if (signalfd_sig_pending(p, t, state->sfd_set) != 0)
 579                 revents |= POLLRDNORM | POLLIN;
 580 
 581         mutex_exit(&state->sfd_lock);
 582 
 583         *reventsp = revents & events;
 584         if ((*reventsp == 0 && !anyyet) || (events & POLLET)) {
 585                 sigfd_proc_state_t *pstate;
 586                 sigfd_poll_waiter_t *pw;
 587 
 588                 /*
 589                  * Enable pollwakeup handling.
 590                  */
 591                 mutex_enter(&p->p_lock);
 592                 if ((pstate = (sigfd_proc_state_t *)p->p_sigfd) == NULL) {
 593 
 594                         mutex_exit(&p->p_lock);
 595                         pstate = kmem_zalloc(sizeof (*pstate), KM_SLEEP);
 596                         list_create(&pstate->sigfd_list,
 597                             sizeof (sigfd_poll_waiter_t),
 598                             offsetof(sigfd_poll_waiter_t, spw_list));
 599                         pstate->sigfd_pollwake_cb = signalfd_pollwake_cb;
 600 
 601                         /* Check again, after blocking for the alloc. */
 602                         mutex_enter(&p->p_lock);
 603                         if (p->p_sigfd == NULL) {
 604                                 p->p_sigfd = pstate;