[PATCH] pselect: Use linux pselect syscall when available

Nic Dade nic.dade at gmail.com
Sat Dec 19 03:28:43 UTC 2015


> real code / testcase

Should be easy.... yup. With an unpatched uclibc this code hangs in
pselect() because the pending signal fires during the window between the
sigprocmkas() and the select(). A proper pselect() returns with errno EINTR.

---------------------------------------------------------------------------------------------
#define _GNU_SOURCE // gimme the good stuff

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/select.h>

// our SIGALRM handler
void handler(int signum) {
        (void)signum;
        write(1, "got signal\n", 11);
}

int main(int argc, char** argv) {
        (void)argc;
        (void)argv;

        // block SIGALRM. We want to handle it only when we're ready
        sigset_t wait_mask, mask_sigchld;
        sigemptyset(&mask_sigchld);
        sigaddset(&mask_sigchld, SIGALRM);
        sigprocmask(SIG_BLOCK,  &mask_sigchld, &wait_mask);
        sigdelset(&wait_mask, SIGALRM);

        // register a signal handler so we can see when the signal arrives
        struct sigaction act;
        memset(&act, 0, sizeof(act));
        sigemptyset(&act.sa_mask); // just in case an empty set isn't all
0's (total paranoia)
        act.sa_handler = handler;
        sigaction(SIGALRM, &act, NULL);

        // send ourselves a SIGARLM. It will pend until we unblock that
signal in pselect()
        printf("sending ourselves a signal\n");
        kill(getpid(), SIGALRM);

        printf("signal is pending; calling pselect()\n");
        int rc = pselect(0, NULL, NULL, NULL, NULL, &wait_mask);
        int e = errno;
        printf("pselect() returned %d, errno %d (%s)\n", rc, e,
strerror(e));

        return 0;
}


On Fri, Dec 18, 2015 at 10:37 AM, Rich Felker <dalias at libc.org> wrote:

> On Thu, Dec 17, 2015 at 09:05:48PM +0100, Waldemar Brodkorb wrote:
> > Hi Nicolas,
> > Nicolas S. Dade wrote,
> >
> > > Linux has a pselect syscall since 2.6.something. Using it
> > > rather than emulating it with sigprocmask+select+sigprocmask
> > > is smaller code, and works properly. (The emulation has
> > > race conditions when unblocked signals arrive before or
> > > after the select)
> >
> > Did you see the race condition in real code or do you have
> > a testcase for it?
>
> The race conditions should be easy to reproduce since you have a
> relatively huge syscall-latency-length (several us) window to race
> with. Fake pselect implementations are historically known to be
> harmful; the whole reason pselect was invented was to fix these races
> in old code that used sigprocmask followed by select.
>
> Rich
>


More information about the uClibc mailing list