[Top][All Lists]

[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 20:45:59 +0200

On Sep 29 2011, Jörg F. Wittenberger wrote:

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.

                ((again bool #f))
                (lambda ()
                  (when (fx>= bufindex buflen)
                        (let loop ()
                          (and (not iclosed)
                               (let ([n ((foreign-lambda*
                                          ((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))])
                                   (thread-wait-for-i/o! fdr #:input)

Try fixing the problem by replacing

*again=(r==-1)&&(errno == EAGAIN);


*again=(r==-1)&&((errno == EAGAIN) || (errno == EINTR));

And do so again in the output case.

So far I'm in a bogus situation:

a) I applied that sigaction-patch.  Since I've not seen the problem,
 which has eaten my nerves for about a week.

b) still I've seen those kinda rare events, where I had some indication
 of i/o-threads dying in unexpected way with no good clean up.
 But those indications where wild guess work as you do, when you just
 have no clue how to force the case to happen.

c) Those lost-in-io cases did not show up... within an all too short time
 to take the observation as serious.  But still long enough to inform
 you of my personal feeling that there might be a connection.

Alan, I'd give Felix' code a shot with the EINTR case fixed.  Looks kinda
good from my bogus poit of view.

reply via email to

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