[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Question about handling SIGINT properly in Guile

From: Maxime Devos
Subject: RE: Question about handling SIGINT properly in Guile
Date: Mon, 15 Apr 2024 01:12:35 +0200

>Try running the simple reproduction included below. Try typing ^C
(Ctrl+C) soon after the program begins. Sometimes "WORK" is run
once, and sometimes "WORK" is run twice. What do I need to do to make
"WORK" run only once in this instance?
>(define quit? #f)
>(sigaction SIGINT (lambda (arg)
 >                   (pk "SIG" arg)
  >                  (set! quit? #t)))
>(let loop ()
> (pk "QUIT-CHECK")
> (if quit?
>      (begin (format #t "Quitting!~%") (exit 0))
>      (begin (pk "WORK" (do ((i 0 (+ i 1))
>                             (sum 0 (+ sum i)))
>                            ((= i 1000) sum)))
>             (pk "SLEEP" (sleep 10))
>             (loop))))
>I understand that signal handlers are asynchronous (Asyncs) and aren't
guaranteed to run immediately. However, I expect them to be run before
the next primitive call. Am I doing something wrong?

(Disregard my previous e-mail – AFAIK nothing I said there is false, but its 
contents is beside the point).

Four things:
• Even in C, there can be a distance between sending a signal and receiving a 
signal. (At least, I assume so, I haven’t actually investigated this.) So Guile 
might simply not have received the SIGINT yet. However, given the (sleep 10), I 
doubt this is the case here
• I might misremember, but I don’t think there actually is a promise that 
scm_async_tick or equivalent is run before/during/after a primitive – as I 
understand it, the promise is that signals will be handled without much of a 
delay, doing scm_async_tick next to a syscall or equivalent is just an 
implementation. (Though IIRC scm_async_tick is done as part of SCM_SYSCALL*)
• You might want to check if scm_async_tick is done _after_ the syscall (or, 
more precisely, the call to whatever is in the C library) or _before_. In this 
case, if you are depending on (sleep ...) to do the tick, then it should be 
_after_. But maybe it is instead done _before_. (However, I’d think that ‘pk’ 
(indirectly) does a scm_async_tick, so that shouldn’t matter?)
• Better put a (call-with-blocked-asyncs ...) or whatever is the exact name 
around all the I/O unless you’re sure that the port I/O procedures can deal 
fine with the re-entrancy.

I don’t expect any of these to solve the problem (except perhaps 3) but it’s 
something you could investigate.

Best regards,
Maxime Devos.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]