On Sep 29 2011, Alan Post wrote:
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.
Yes. That looks quite like the code in the process-io-ports
as I posted before.
(let-location
((again bool #f))
(lambda ()
(when (fx>= bufindex buflen)
(let loop ()
(and (not iclosed)
(let ([n ((foreign-lambda*
int
((int fd) (scheme-pointer buf) (int
s) ((c-pointer bool) again))
"int r = read(fd, buf, s);
*again=(r==-1)&&(errno == EAGAIN); return(r);")
fdr buf buffer-size (location again))])
(cond
(again
(thread-wait-for-i/o! fdr #:input)
(loop))