Hi, Andreas Rottmann <m...@r0tty.org> skribis:
>> Andreas Rottmann <m...@r0tty.org> skribis: >> >>> Andreas Rottmann <m...@r0tty.org> writes: >>> >>>> [...] I isolated the cause; the following snippet hangs on Guile 2.2 >>>> and 3.0, while it worked as expected on 2.0: >>>> >>>> ;; ------------------ >>>> (import (rnrs)) >>>> >>>> (let* ((p (pipe)) >>>> (in (car p)) >>>> (out (transcoded-port (cdr p) (make-transcoder (utf-8-codec))))) >>>> (put-datum out "foo") >>>> (flush-output-port out) >>>> (display "Should have written to pipe by now, attempting reading a >>>> byte\n") >>>> (display "Got") >>>> (display (get-u8 in)) >>>> (newline)) >>>> ;; ------------------- >>>> >>>> It seems the underlying port is no longer flushed to the OS, so the >>>> `get-u8` now hangs waiting for input, starting with Guile 2.2. >>>> >>> I'd like to add that this is indeed not passing data to the OS, as >>> verified by strace. Also, I have now figured out the commit introducing >>> the regression, namely 8399e7af5 ("Generic port facility provides >>> buffering uniformly"); the commit before (e8eeeeb1d) still runs the >>> above code to completion. >> >> Actually I think the code above behaves as expected. ‘pipe’ returns >> buffered ports by default. When flushing the transcoded port, >> ‘transcoded_port_write’ is called, but then bytes written to the pipe >> are buffered. >> >> The fix is to add: >> >> (setvbuf (cdr p) 'none) >> >> Does that make sense? >> > It makes sense, and I can confirm that it makes the boiled-down example > I posted work. > > However, I'm not sure it is the expected behavior. Regardless of > buffering modes used, I would expect a `flush-output-port` in a "port > stack" (as produced by `transcoded-output-port`) to propagate all the > way to the OS. It seems that was the case in Guile 2.0, as I'm pretty > sure I observed the "breaking" behavior change with 8399e7af5 applied, > and not with the commit preceding it. Port types don’t have a “flush” operation, only “write”. Thus, it’s impossible to define a port type that would propagate flushes. There are pros and cons I guess, but it seems like a reasonable choice to me. When implementing a “proxying” port type like ‘transcoded-port’ that does its own buffering, it’s probably OK to say that it’s the proxy’s responsibility to ensure there’s no double-buffering taking place. > If the current behavior is indeed the intended one, we should make sure > the docs somehow reflect this caveat, as I imagine it may surprise > future Guile users which happen to use its R6RS support and pipes in > combination. Maybe we should not document this specific combination but rather the more general issue? I’m not sure how to do that. Thoughts? Thanks, Ludo’.