[plt-scheme] writing to subprocess's stdin and then...

From: Eli Barzilay (eli at barzilay.org)
Date: Tue Jun 17 01:40:39 EDT 2008

On Jun 16, YC wrote:
> Hi -
> I am trying to write to a subprocess's stdin (and then to read from its
> stdout) without much success.  I roughly have the form of
> 
>   (let-values (((p pout pin perr)
>                 (subprocess #f #f #f cmd)))
>     (write "this is a text" pin)
>     (subprocess-wait p)
>     (parameterize ((current-input-port pout))
>       (lambda ()
>         (read-line))))
> 
> but it doesn't work and I suspect it's due to my misunderstanding of how the
> port works (and most likely just how to use subprocess, period).  The v4
> maually mentions "All provided ports must be file-stream ports" - so does
> that mean I need to first write the output to a file?  I found an example on
> http://www.cs.brown.edu/pipermail/plt-scheme/2006-February/011953.html but
> couldn't figure out how to adopt it toward my needs.

You have the rough idea, but several problems:

* you have a redundant `lambda' which means that you never really get
  to read anything (on toy examples, this will probably be a change
  that will make things work, but see below)

* `write' is probably not a good idea -- it will print something with
  the double quotes.

* after you write, you'd want to flush `pin', or if you expect the
  program to get just that, then you'd want to close it (so your
  program will not sit there waiting for more stuff)

* finally, the biggest problem is a conceptual one: you read stuff
  from the output only after the process has finished -- but what if
  it spits out a lot of data?  In that case, it will not finish, and
  instead just sit there waiting for you to read that data, and you'll
  be getting into a very common race condision with subprocesses.

  What you really need is to do the reading in a thread, so the
  process can continue running.  It might seem strange at first, but
  when there's a lot of data then *someone* needs to hold it, and the
  OS will hold only a very small amount (and for good reasons).  Your
  thread will need to do just that accumulation (or it can just to the
  processing, whatever it is).

(You can also see "collects/mzlib/process.ss" for a very extensive
solution.)

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                  http://www.barzilay.org/                 Maze is Life!


Posted on the users mailing list.