Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't communicate with subprocess on Windows #2434

Closed
dmos62 opened this issue Dec 20, 2018 · 2 comments
Closed

Can't communicate with subprocess on Windows #2434

dmos62 opened this issue Dec 20, 2018 · 2 comments

Comments

@dmos62
Copy link

dmos62 commented Dec 20, 2018

I'm trying to write to subprocesses' stdin and read from its stdout; however, it doesn't seem to work; the subprocess does not respond. It works fine if I just launch the subprocess in command line and type. I'm on Windows.

I've made a minimal example. It consists of two filesL test.rkt and echo.rkt. echo.rkt reads stdin and echoes it back to stdout. test.rkt tries to launch echo.rkt with (subprocess ...) and communicate with it through stdin/out.

test.rkt:

#lang racket

(println "start test")

(define-values (proc out in _)
  (let* ([stderr 'stdout]
         [path-to-racket (find-executable-path "racket.exe")]
         [path-to-echo (build-path (current-directory) "echo.rkt")])
    (subprocess #f #f stderr path-to-racket path-to-echo)
    )
  )

(define (block-for-line) (read-line out 'any))

(println (block-for-line)) ; print echo's start notification

(println "abc\n" in) ; print to echo's stdin

(let* ([line (block-for-line)]
       [done (eof-object? line)])
  (when (not done)
    (println (string-append "the echo: " line)) ; print echo's response
    )
  )

echo.rkt:

#lang racket

(println "start echo")
(println (read-line (current-input-port) 'any))

Output when running in Windows Command Prompt:

>racket test.rkt
"start test"
... [blocks indefinitely]

>racket echo.rkt
"start echo"
foobar [typing anything on keyboard and hitting ENTER]
"foobar"
[ctrl-c]

As you can see, when run directly, echo.rkt works fine. While test.rkt blocks indefinitely when reading.

What's interesting is that if you delete echo's last line (the one containing read-line), you get this:

>racket test.rkt
"start test"
"\"start echo\""
error writing to stream port
  system error: The pipe is being closed.; errid=232

As you can see, the "start echo" message gets through. So when executing with subprocess and there's a read-line call in echo.rkt, even println doesn't have an effect, even though it's normally executed before read-line.

By the way, when running from Cygwin, the behaviour is again wrong, but differently. When read-line is in echo.rkt, running test.rkt or echo.rkt doesn't print anything and just blocks, which contrasts with how running with Windows Commands Prompt prints start test and then blocks. If read-line is commented out in echo.rkt, behaviour is as expected, like in Windows Command Prompt.

@mflatt
Copy link
Member

mflatt commented Dec 20, 2018

I think you're running into a common confusion about ports and buffering, especially the way that the buffer mode changes depending on the output device. When stdout is connected to a terminal, it is line-buffered by default. When connected to a pipe or file, it's block buffered by default. A port for a subprocess counts as a pipe. (That difference is a a kind of standard behavior for buffering that Racket adopts.)

If you add (flush-output) or (flush-output in) after each call println, then I think you'll get the results that you expect.

@dmos62
Copy link
Author

dmos62 commented Dec 20, 2018

That fixed it, thanks for the quick reply! I wasn't aware that ports were buffered by default.

Careful reading would have helped me here, but even when I knew what I was looking for it took some 10 minutes to find it in the docs. As a newcomer, I find that the docs could benefit from having community provided examples. From my experience, clojuredocs.org is a great example of that.

By the way, flushing manually also made it work on Cygwin; I guess Cygwin was triggering block buffering in all cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants