> In a word? Badly. :) Especially when threads were involved, though in some

> ways it was actually better since you were less likely to core perl.
> 
> Threads and signals generally don't mix well, especially in any sort of 
> cross-platform way. Linux, for example, deals with signals in threaded 
> programs very differently than most other unices do. (Both ways make
sense, 
> they just aren't at all similar)

Though what you said is largely correct, there are way to use signal safely
with threads.

Signals are divided into 2 category, sync or async. The sync signals include
SIGSEGV, SIGBUS etc. They must be handled inside signal handler. As long as
the crash does not happen inside mutext/condvar block, it will be safe to
get out of the trouble using siglongjmp on most platforms. For async
signals,
it is very risky to use siglongjmp(), since the jmpbuf may not be correct.
The alternative is to use sigwait() family. See some examples.

A) to handle sync signal

        int sig;

        foo() {
        sig = sigsetjmp(interpreter->jmpbuf);

        if (sig == 0) {
                for (;;) { DO_OP(); }
      } else if (sig == SIGSEGV) {
                // do someting
        } else if (sig == SIGBUS) {
                // do something
        }
        }

        void signal_handler(int sig) {
                siglongjmp(current_interpreter()->jmpbuf, sig);
        }

The above code is safe on most platform. But it should be used in a
controlled
fashion, so we can correct recover from the error. If it does not work on
some
platform, we can use alternative scheme.
        foo () {
        while (interpreter->sig == 0) {
                DO_OP();
        }
        if (interpreter->sig == SIGSEGV) {
                ...
        }
        }

        void signal_handler(int sig) {
                current_interpreter()->sig = sig;
        }

Since the pthread_self() may not be available inside signal_handler(), we
need to design some global data structures to find current interpreter.

B) wrong way handle async signal (was used in Java)

        mutex_lock();
        if (sigsetjmp(interpreter->jmpbuf)) {
                cond_wait(...);
        } else {
                // PANIC;
        }

The above code will not work reliable on any platform. The siglongjmp
will not be able to restore mutex correctly, even only one mutex is
involved here.

C) correct way to handle async signal such as CTRL-C

        void async_signal_handler_thread_function() {
                while (sigwait()) {
                        handle signal
                }
        }

We create one thread for all async signal, and let everyone else mask async 
signal off. This scheme can handle signal reliably under threads.

Hong

Reply via email to