TOC   Previous   Next

How

The pselect() call:

    ready = pselect(nfds, &readfds, &writefds, NULL, timeout, &sigmask);

is equivalent to atomically performing the following steps:

    sigset_t origmask;

    sigprocmask(SIG_SETMASK, &sigmask, &origmask);
    ready = select(nfds, &readfds, &writefds, NULL, timeout);
    sigprocmask(SIG_SETMASK, &origmask, NULL);  /* Restore signal mask */
	

pselect() is safe because signals in sigmask are only unblocked inside the system call.

pselect() allows us to safely wait for the signal:

    sigset_t emptyset, blockset;
    struct sigaction sa;

    /* Block the signal */
	
    sigemptyset(&blockset);
    sigaddset(&blockset, SIGUSR1);

    sigprocmask(SIG_BLOCK, &blockset, NULL);

    /* Install handler */
	
    sa.sa_sigaction = handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    sigaction(SIGUSR1, &sa, NULL);
    
    /* Unblock signal; wait for ready fd or signal */
	
    sigemptyset(&emptyset);    /* Signal mask to use during pselect() */
	
    ready = pselect(nfds, &readfds, NULL, NULL, NULL, &emptyset);
    
    /* Remaining code as for select() */
	
    if (ready > 0) {
        printf("%d file descriptors ready\n", ready);
    } else if (ready == -1 && errno == EINTR) {
        if (gotSig)
            printf("Got signal\n");
    } else {
        /* Some other error */
    }

(C) 2006, Michael Kerrisk