system* temporarily re-binds signal handlers to prevent the child process from killing the parent. Thus, it is not thread safe with regard to SIGINT (or SIGQUIT if available). So, your code has a race condition with respect to the signal handler. This common resource can, in principle, be handled the usual way by, for example, utilizing a mutex: (use-modules (ice-9 threads)) (define sigint-mutex (make-mutex)) (define thread (call-with-new-thread (lambda () (with-mutex sigint-mutex (system* "echo" "foo"))))) (with-mutex sigint-mutex (sigaction SIGINT (lambda (sig) (peek "SIGINT handler") (exit 1))) (for-each (lambda _ (sleep 1)) (iota 30))) (join-thread thread) (display "normal exit\n") But if this was real code, another way would be to make sure that the code blocks are run in the order that you wish (which you did not want here since your very purpose was to provoke the collision of resources). I'm leaving this bug open. *Should* system* re-bind the signal handlers? Should it really protect itself from the child? If so, we should probably document this behaviour in the reference manual. Best regards, Mikael On Tue, Apr 2, 2024 at 4:28 PM Christopher Baines wrote: > I've encountered a situation where signal handlers don't seem to > run. With the following program, sending it SIGINT won't trigger the > handler, however if you remove the system* call, then the handler will > run. > > (use-modules (ice-9 threads)) > > (call-with-new-thread > (lambda () > ;; Remove the following system* call to fix the handler > (system* "echo" "foo"))) > > (sigaction SIGINT > (lambda (sig) > (peek "SIGINT handler") > (exit 1))) > > (for-each > (lambda _ > (sleep 1)) > (iota 30)) > > (display "normal exit\n") >