Hi,

I'm writing a library that intends to have safe, prompt delivery of signals mixed with select() calls. I want to actually be able to do interesting things (involving non-reentrant functions) safely.

So the logical way is to just set a flag from the signal handler and poll for it before/after the select. But then there's this race condition:

    while (1) {
        handle_signals();
        /* SIGNAL ARRIVES HERE */
        select(...);
        handle_signals();
        ...
    }

That signal will be held until something happens to make select() return. That's no good. I discovered the pselect() call to solve this problem. pselect() atomically resets the signal mask for the duration of the select. So this code will work:

    sigprocmask(SIG_SETMASK, &full_set, NULL);
    handle_signals();
    while (1) {
        retval = pselect(..., &empty_set);
        if (retval < 0 && errno == EINTR) {
            handle_signals();
        }
        ...
    }

But I want my application to run on Linux, where pselect() is a horrible lie. (What they have is no different than me doing the sigprocmask() calls myself; it's not atomic.) I need something else.

So I googled. On the Linux kernel mailing list, this question came up. Alan Cox's solution was to use siglongjmp(). Something like this:

    while (1) {
        sigsetjmp(&env, true);
        jump_is_safe = 1;
        handle_signals();
        retval = select(...);
        jump_is_safe = 0;
        ...
    }

where the signal handler, in addition to setting a flag, jumps if jump_is_safe is set. There's no blocking select with signals waiting, because the signal handler jumps back to the handle_signals() line in that region.

So here's my question:

Under pth and other threading libraries where select() is more than a simple system call, is this siglongjmp() safe? I.e., does pth allocate memory or do anything interesting from within select()? Do you know of any other libraries that do so?

There are other methods I could use (mostly writing to a pipe from the signal handler), but I'd prefer not to because those mean extra system calls. This is library code, so I'd like to keep it broadly useful by not sucking performance-wise.

Also, is pthread_getspecific safe to call from signal handlers? I don't think there's any way to distinguish which thread received a pthread_kill()-style signal without using this call from a signal handler. (Unless I block signals everywhere and use sigpending()/sigsuspend(), but then I can't check descriptors anymore...)

handle signals safely in multiple threads without using this call. I can at guarantee that no signal on a thread while that same thread is executing pthread_getspecific. Would that help?

On an unrelated note, the webpage (<http://www.gnu.org/software/pth/>) says to subscribe with a mail to [EMAIL PROTECTED] with "subscribe pth-users" in the body. That's wrong; it sends back a message like "pth-users is not a complete address. Try 'subscribe <list> [address]' (address defaults to the sender)." I tried "subscribe [EMAIL PROTECTED]"...thus the confimation request to the list. (Sorry.) Apparently the list is implied by sending it to pth-users-request@ rather than to majordomo@ or something. I think the website and majordomo help text should be tweaked. The correct syntax is apparently just "subscribe [address]".

Thanks,
Scott Lamb

______________________________________________________________________
GNU Portable Threads (Pth)            http://www.gnu.org/software/pth/
Development Site                      http://www.ossp.org/pkg/lib/pth/
Distribution Files                          ftp://ftp.gnu.org/gnu/pth/
Distribution Snapshots                 ftp://ftp.ossp.org/pkg/lib/pth/
User Support Mailing List                            [EMAIL PROTECTED]
Automated List Manager (Majordomo)           [EMAIL PROTECTED]

Reply via email to