Let me try a demonstration showing just the main thread:
(define (restart-read fd buf isize)
; call read(2), on the self-pipe, which blocks
(let ((r (file-read fd buf isize)))
(if (= -1 r)
; ah, a signal was delivered. In Chicken, the signal
; delivery to the prcoess causes this error, but the
; Scheme code signal handler might not have been
; delivered. In this case, it means that I haven't
; written a byte to the self-pipe yet.
;
(if (= errno EINTR)
; restart the read. Normally, we would have written
; to our self-pipe already (as the signal is delivered
; the moment we return from our syscall.), but in
; Chicken, I'm not sure our deferred Scheme code has
; been called. When does that happen? If it hasn't
; happened yet, I'll block in this routine, and the
; deferred signal handler will never run.
;
; I need a way to guarantee that the deferred signal
; handler has already been run, before I call any other
; syscall.
;
(restart-read fd buf isize))
; something else went wrong, die.
(io-error "read"))))
Does that story make more sense? Chicken may already behave this
way, I'm not sure how long it waits/when it delivers a deferred
signal. The critically important thing is that it do so before
making another syscall.