chicken-users
[Top][All Lists]
Advanced

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

Re: [Chicken-users] EINTR with self-pipe signal trampoline


From: Jörg F . Wittenberger
Subject: Re: [Chicken-users] EINTR with self-pipe signal trampoline
Date: 29 Sep 2011 19:13:00 +0200

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))


Here the thread is scheduled to wait again if EAGAIN has been in errno.

But you are right: the EINTR call is not handled.
That's a bug for sure.  I need to fix it.

/Jörg





reply via email to

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