#640 mt: module/linux error

lisp error
open
5
2012-04-24
2012-04-24
Sam Steingold
No

$ make full-mod-check MODULES=bindings/glibc
...

(DEFPARAMETER *SIGACT* (SHOW (LINUX:signal-action-retrieve LINUX:SIGINT)))
#S(LINUX:sigaction :SA_HANDLER NIL :SA_MASK #S(LINUX:sigset_t :VAL #()) :SA_FLAGS 0 :SA_RESTORER #<FOREIGN-ADDRESS #x00002AB7D29E4420>)
EQL-OK: *SIGACT*
(DEFPARAMETER *SAVEHANDLER* (LINUX:sa-handler *SIGACT*))
EQL-OK: *SAVEHANDLER*
(DEFPARAMETER *SIGNALS* NIL)
EQL-OK: *SIGNALS*
(DEFUN TEST-HANDLER (S) (DECLARE (COMPILE)) (PUSH S *SIGNALS*))
EQL-OK: TEST-HANDLER
(PROGN (SETF (LINUX:sa-handler *SIGACT*) #'TEST-HANDLER) (LINUX:signal-action-install LINUX:SIGINT *SIGACT*))
EQL-OK: NIL
*SIGNALS*
EQL-OK: NIL
(KILL (PROCESS-ID) :SIGINT)
EQL-OK: *** - Condition of type SYSTEM::INTERRUPT-CONDITION.
Bye.

I guess the signal is received by a different thread than the thread which has the signal handler installed.
I wonder if this test could be adapted to the MT clisp build.
Maybe the correct solution is to remove the signal ffi code altogether and implement that separately?
Vladimir, this is your call.

GNU CLISP 2.49+ (2010-07-17) (built 3544263222) (memory 3544285389)
Software: GNU C 4.6.1
gcc -W -Wswitch -Wcomment -Wpointer-arith -Wreturn-type -Wmissing-declarations -Wimplicit -Wno-sign-compare -Wno-format-nonliteral -falign-functions=4 -pthread -g -O0 -DDEBUG_OS_ERROR -DDEBUG_SPVW -DDEBUG_BYTECODE -DSAFETY=3 -DENABLE_UNICODE -DMULTITHREAD -DPOSIX_THREADS -DDYNAMIC_FFI -DDYNAMIC_MODULES libgnu.a -lreadline -lncurses -ldl /usr/lib/libavcall.a /usr/lib/libcallback.a -lsigsegv
SAFETY=3 TYPECODES WIDE_HARD SPVW_BLOCKS SPVW_MIXED TRIVIALMAP_MEMORY
libsigsegv 2.9
libreadline 6.2
libffcall 1.11
Features:
(READLINE REGEXP WILDCARD SYSCALLS I18N LOOP COMPILER CLOS MOP CLISP ANSI-CL COMMON-LISP LISP=CL INTERPRETER LOGICAL-PATHNAMES MT
SOCKETS GENERIC-STREAMS SCREEN FFI GETTEXT UNICODE BASE-CHAR=CHARACTER WORD-SIZE=64 PC386 UNIX)
C Modules: (clisp i18n syscalls regexp readline)
Installation directory: /home/sds/src/clisp/current/build-mt-g/
User language: ENGLISH
Machine: X86_64 (X86_64) t520sds [127.0.1.1]

Discussion

  • Signals and threads do not play nice in general.
    Synchronous signals (SIGSEGFAULT, SIGPIPE, SIGFPE) are always delivered and
    signal handler is invoked in the thread that caused them.
    Asynchronous ones (all the rest - SIGINT, SIGHUP, SIGCONT, SIGALRM, etc) are
    quite different and there are two approaches to handle them .
    1. If signal handler is present - it can be invoked in any thread
    that has not blocked the delivered signal. This means that only single thread
    can deterministically register signal handler (unblock the signal and block it
    in all the other threads).
    2. Use a dedicated thread to wait & handle all signals (via sigwait()) and block
    all signals in other threads. Big advantage here is that after sigwait()
    returns you are allowed to use any function not just the async-signal safe ones
    as in the case with signal handler (for a list see:
    http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html ).

    CLISP uses the sigwait() approach. So even though you register a signal handler
    the delivery of this signal is blocked in all threads and sigwait() comes to
    action.

    CLISP handles internally following asynchronous signals:
    SIGCLD: to prevent zombies when forking
    SIGINT: to act on CTRL-C
    SIGALRM & SIGUSR2: to implement CALL-WITH-TIMEOUT
    SIGUSR1: to implement THREAD-INTERRUPT
    SIGWINCH: to update terminal line length
    And all terminating signals (SIGQUIT, SIGABRT, SIGTERM, SIGKILL)
    I am not sure it is good idea to allow installation of signals handlers for
    the above.

    As general solution we may maintain a central registry of signal handlers
    and threads in which they have been registered (NIL for "does not care" thread)
    and invoke these handlers from dedicated sigwait-ing thread via
    THREAD-INTERRUPT (the same way as CALL-WITH-TIMEOUT works now).
    If we go in this way there are two questions:
    1. should we allow multiple threads to register handler for the same signal?
    2. should we allow single thread to register several handlers for the same
    signal?

    And all the above is POSIX specific of course.