bug#39610: R6RS `flush-output-port` not playing along with `transcoded-port`

Ludovic Courtès <[email protected]>
Newsgroups gmane.lisp.guile.bugs
Message-ID <[email protected]>
Hi,

Andreas Rottmann <[email protected]> skribis:

>> Andreas Rottmann <[email protected]> skribis:
>>
>>> Andreas Rottmann <[email protected]> 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’.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.