On Sat, 13 Apr 2024, Vijay Marupudi <vijaymarup...@gatech.edu> wrote: > Hello folk of guile-user, > > I am trying to create a simple Guile program that continues to perform a > task until an interrupt signal is sent. However, I am unable to > deterministically end the program when SIGINT is sent, as the > interrupt handler does not run soon after the call to (sleep ...) ends. > > 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?
Depending where the signal is sent, you will have two WORKs. For example: --8<---------------cut here---------------start------------->8--- (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)) (kill (getpid) SIGINT) ;; Ctrl-C emulation. (loop)))) --8<---------------cut here---------------end--------------->8--- > 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? So there is two things with signals. First, when a process get a signal queued, the OS only deliver the signal -- at least on linux -- when going back to user-space. Typically, before the process get re-scheduled or after a system call. So sending a signal is not immediate. Furthermore, Guile also queues the signals and deliver them to threads with async marks I think. -- Olivier Dion oldiob.ca