Hi !
I'm having some trouble with simple sockets operations, and I'm not sure whether this is a bug, or whether I definitely misunderstood the documentation.
Here is a sample code:
;; Create a server (define node-socket (open-tcp-server (list port-number: 8284 eol-encoding: 'cr-lf)))
;; Set it non blocking (input-port-timeout-set! node-socket 0)
;; read once. Should return EOF because no one tried to connect to the ;; server (define c (read node-socket))
;; returns #t (eof-object? c)
;; Drink a coffee and read again. ;; It should return eof again for no one is connected (define d (read node-socket))
*** ERROR IN ##thread-deadlock-action! -- Deadlock detected
Hum... Deadlock ? Should I do something specific after "failing" to read the socket to let some other expression to read it again ? Or is it a bug^Wundocumented feature in the non-blocking ports routines ?
This happens as well on beta 22 as on beta 17.
Does it happen at yours too on a mac/windows ? Do you use non blocking IO a different manner, and that works ?
Regards,
Adrien
Afficher les réponses par date
On 6-Aug-07, at 2:09 PM, Adrien Pierard wrote:
Hi !
I'm having some trouble with simple sockets operations, and I'm not sure whether this is a bug, or whether I definitely misunderstood the documentation.
No, it's a bug in the tcp-server port implementation. To fix it, in procedure ##make-tcp-server-port in file lib/_io.scm, replace the lines:
;; the read would block, so wait and then try again
(macro-port-mutex-unlock! port) (let ((continue? (or (##wait-for-io! (macro-tcp-server-port-rdevice- condvar port) (macro-port-rtimeout port)) ((macro-port-rtimeout-thunk port))))) (macro-port-mutex-lock! port) ;; regain access to port (if continue? (loop) #!eof)))
with
;; the read would block, so wait and then try again
(macro-port-mutex-unlock! port) (let ((continue? (or (##wait-for-io! (macro-tcp-server-port-rdevice- condvar port) (macro-port-rtimeout port)) ((macro-port-rtimeout-thunk port))))) (if continue? (begin (macro-port-mutex-lock! port) ;; regain access to port (loop)) #!eof)))
I noticed a few other cases like this in lib/_io.scm . They will be fixed in the next release.
Marc
At this occasion maybe I'd report something I've recently noticed:
On Linux, with beta 21, when you create a named pipe from the shell ($ mkfifo fifo), then, if no writers are connected,
(define f (open-input-file "fifo")) returns immediately, and
(read-line f) returns #!eof immediately. (Only after a writer connects, read-line blocks until data is present.)
"Usually" under unix (without switching on non-blocking I/O) (at least using Perl) the open call blocks if no reader is connected. The read call returns eof after the last writer has closed, and continues to immediately return eof until another writer connects. For this reason, after the first eof I re-open fifo's in my Perl code (to avoid running in a 100% cpu burning loop). This is somewhat weird, too, of course, but I take that is just how it could sensibly work that doesn't differentiate between several writers. (Unix domain sockets don't have these problems of course.)
Now I'm not sure if open-input-file really has to be made to behave the same way in Gambit; in my app it wasn't a problem (not sure anymore why, but I think I moved on to unix domain sockets anyway in the end). In any case I would definitely not recommend a fix that would require a stat(2) call on the file before each open to find out whether it is a fifo (because of the overhead and the race involved). If it can be fixed in another way then fine.
Christian.