chicken-users
[Top][All Lists]
Advanced

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

Re: [Chicken-users] Pipe and thread problem


From: Moritz Heidkamp
Subject: Re: [Chicken-users] Pipe and thread problem
Date: Wed, 24 Oct 2012 23:10:20 +0200

Hey Chickeneers,

out of curiosity I implemented (probably horribly inefficitent)
thread-aware replacements for open-input-file* and open-output-file*
(see below). While implementing them I came across something that I
didn't quite understand: file-read and file-write raise errors whenever
the underlying syscall returns -1. However, in this case I want to
handle some error situations (i.e. EINTR, EAGAIN and EWOULDBLOCK). The
only way I could find to do this is by dispatching on (errno) in the
excpetion handler. However it looks like (errno) is not thread-safe so
it might actually return a different value when my handler is run. Is
this observation correct? Perhaps we should mention this in errno's
documentation? Also, to make it possible to handle these errors I
suggest to add the respective errno to the condition object. This would
be thread-safe as the posix unit declares disable-interrupts. Thoughts?

OK, here we go. It seems to work with your program, Aaron:

(define (open-input-fd fd)
  (make-input-port
   (lambda ()
     (let loop ()
       (thread-wait-for-i/o! fd #:input)
       (or (condition-case
               (string-ref (car (file-read fd 1)) 0)
             (exn (exn i/o file)
                  (select (errno)
                    ((errno/intr errno/again errno/wouldblock)
                     #f)
                    (else (signal exn)))))
           (loop))))
   (lambda ()
     (nth-value 0 (file-select fd #f 0)))
   (lambda ()
     (file-close fd))))

(define (open-output-fd fd)
  (let ((port (open-output-file* fd)))
    (make-output-port
     (lambda (buffer)
       (let loop ((buffer buffer) (len (string-length buffer)))
         (thread-wait-for-i/o! fd #:output)
         (let ((written (condition-case
                            (file-write fd buffer)
                          (exn (exn i/o file)
                               (select (errno)
                                 ((errno/intr errno/again errno/wouldblock)
                                  #f)
                                 (else (signal exn)))))))
           (if written
               (unless (= written len)
                 (loop (substring buffer written len) (- len written)))
               (loop buffer len)))))
     (lambda ()
       (close-output-port port))
     (lambda ()
       (flush-output port)))))

Oh yeah, and note the lame solution of opening the output FD with
open-output-file* -- this is only because there is no flush-file in
posix. Perhaps worth adding?

Moritz

Aaron Patterson <address@hidden> writes:

> On Wed, Oct 24, 2012 at 08:04:37AM -0400, Felix wrote:
>> From: Aaron Patterson <address@hidden>
>> Subject: [Chicken-users] Pipe and thread problem
>> Date: Tue, 23 Oct 2012 14:30:57 -0700
>> 
>> > Hi, I'm trying to simulate reading from a TTY that writes every two
>> > seconds.  I want to do this with a pipe and two threads, one thread
>> > writes every N seconds, while the other reads any data available on the
>> > pipe.
>> > 
>> > Unfortunately, my code just hangs.  After speaking with the fine people
>> > in #chicken, it seems that this may be a bug.  We played with different
>> > calls to put the threads to sleep, and different functions to read data,
>> > but they all ended up freezing at some point.
>> 
>> The ports obtained from calls to "open-[input|output]-file*" use
>> internally the "stream-port" class (ports on FILE* streams, in this
>> case created via fdopen(3)). These are not thread-aware, AFAICT. Ports
>> created for socket-fd's (tcp.scm) and processes (posixunix.scm, see
>> specifically ##sys#custom-[input|output]-port") apparently do.
>
> Is there a different way I should be opening the pipe so that it is
> thread aware?



reply via email to

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