[racket] Possible bug involving sync on tcp ports

From: Brett Stahlman (brettstahlman at gmail.com)
Date: Sun Sep 14 11:03:39 EDT 2014

On Sun, Sep 14, 2014 at 9:49 AM, Matthew Flatt <mflatt at cs.utah.edu> wrote:
> I'll push a repair to make `rnrs/io/ports-6` ports work right with
> `sync`.

Excellent! Thanks.

>
> There's not really a way to get the OS-process-level stdin and stdout
> in Racket, except by using scheme_make_fd_input_port() via
> `ffi/unsafe`. The intent is that the initial ports, which correspond to
> stdin and stdout, can be made inaccessible to untrusted code by
> changing the `current-input-port` and `current-output-port` parameters.
>
> Usually, it's best to just use `(current-input-port)`. The initial
> parameter value corresponds to stdin for a stand-alone Racket process;
> in other cases, a program should normally accept whatever adjustments
> are made by its environment. If you really need the OS-process-level
> stdin and stdout, through, then `ffi/unsafe' can reach them.

Understood. That certainly works for my use-case...

Brett S.

>
> The `standard-input-port` function in Racket's R6RS implementation,
> meanwhile, returns the current input port at the time that the R6RS
> library was loaded. So, it's not necessary stdin in the sense of the OS
> process, but it's "stdin" in the sense of the being the designated
> source for input when the library starts.
>
> At Sun, 14 Sep 2014 09:38:49 -0500, Brett Stahlman wrote:
>> On Sun, Sep 14, 2014 at 9:23 AM, Matthew Flatt <mflatt at cs.utah.edu> wrote:
>> > I think the problem is in `standard-input-port` from `rnrs/io/ports-6`.
>> >
>> > If you use `current-input-port` instead of `standard-input-port`, does
>> > the client behave correctly?
>>
>> It does indeed! Can't recall why I used standard-input-port to begin
>> with, but I'm thinking this could account for some of the weirdness
>> I've been seeing. I didn't mention it in my original posts, but part
>> of the reason I went to such a convoluted strategy for peeking and
>> reading ports was that byte-ready? was blocking as well. Actually,
>> I've been planning to change the client/server architecture entirely -
>> to one in which each port reader operates in a dedicated thread, and
>> simply blocks until a new form can be read, at which point it writes
>> the data to an async channel to be processed at a higher level - but I
>> didn't want to proceed without resolving these issues...
>>
>> Out of curiosity, what is the proper way to set the current input port
>> to stdin (if somehow it's been changed from the default)? (It hasn't,
>> in my case, but perhaps the reason I went to standard-input-port in
>> the first place was that there didn't appear to be any guarantee that
>> the current input port would be stdin...)
>>
>> Thanks,
>> Brett S.
>>
>> >
>> > At Sun, 14 Sep 2014 08:20:26 -0500, Brett Stahlman wrote:
>> >> On Sep 14, 2014 7:56 AM, "Matthew Flatt" <mflatt at cs.utah.edu> wrote:
>> >> >
>> >> > It's possible that something is wrong with `sync` and TCP ports ---
>> >> > although the test suite at least includes that combination --- but can
>> >> > you provide a complete program?
>> >> >
>> >> > For example, I'm interested in what `handle-rdy-to-send` does. In the
>> >> > part that you show, the function will be triggered when one byte is
>> >> > available on stdin. If `handle-rdy-to-send` tries to read more bytes
>> >> > than are immediately available, then it can block; i.e., the blocking
>> >> > part could be in `handle-rdy-to-send`, not in `sync`. That would also
>> >> > explain why using `sync/timeout` doesn't change anything.
>> >>
>> >> Actually, I know it's blocking in the sync (or sync/timeout) because the
>> >> actual code is littered with immediately-flushed printf's, and there's one
>> >> right before and one right after the sync call. I will try to put together
>> >> a version to send you, though. Would you prefer it with the debug printf's
>> >> stripped out?
>> >>
>> >> Thanks, Brett S.
>> >>
>> >> >
>> >> > Again, that's just an example of what might be wrong other than `sync`.
>> >> > A complete program would let us sort out the possibilities.
>> >> >
>> >> > At Sun, 14 Sep 2014 06:57:34 -0500, Brett Stahlman wrote:
>> >> > > Hello,
>> >> > >
>> >> > > I have the following loop in a tcp client program that sends forms
>> >> typed by
>> >> > > user at the terminal to a listening server, and receives such forms
>> >> typed by
>> >> > > other clients (broadcast to all clients by the server).
>> >> > >
>> >> > > (define server-msg-evt (wrap-evt in handle-server-msg))
>> >> > > (define rdy-to-send-evt (wrap-evt (standard-input-port)
>> >> handle-rdy-to-send))
>> >> > >
>> >> > > (let loop ()
>> >> > >   (sync rdy-to-send-evt server-msg-evt)
>> >> > >   (loop))
>> >> > >
>> >> > > The problem is that the server-msg-evt isn't reliably ready when the
>> >> server
>> >> > > flushes a message. I know the messages are being sent and flushed
>> >> properly
>> >> > > by
>> >> > > the server because if I type a new form on stdin and hit enter, I see
>> >> the
>> >> > > following sequence:
>> >> > >
>> >> > > 1. Client processes new stdin form in handle-rdy-to-send
>> >> > > 2. Client loops and calls sync
>> >> > > 3. The server-msg-evt is *immediately* ready, and client handles the
>> >> > >    message in handle-server-msg.
>> >> > > Note: The message handled in step 3 may have been sent long before, but
>> >> > > the client remained blocked in sync until the (unrelated) stdin event
>> >> > > unblocked it.
>> >> > >
>> >> > > The really weird part is that the client blocks in this manner even if I
>> >> > > change the sync to a sync/timeout!
>> >> > >
>> >> > > Any clue as to what could be going on here? I'm running both client and
>> >> > > server
>> >> > > in a DOS box on a Windows 7 machine.
>> >> > >
>> >> > > Thanks,
>> >> > > Brett Stahlman
>> >> > > ____________________
>> >> > >   Racket Users list:
>> >> > >   http://lists.racket-lang.org/users
>> >> ____________________
>> >>   Racket Users list:
>> >>   http://lists.racket-lang.org/users
>> ____________________
>>   Racket Users list:
>>   http://lists.racket-lang.org/users

Posted on the users mailing list.