Subject: Re: sb-ext:run-program
From: rpw3@rpw3.org (Rob Warnock)
Date: Fri, 07 Dec 2007 03:30:46 -0600
Newsgroups: comp.lang.lisp
Message-ID: <5padnd6MH5lbj8TanZ2dnUVZ_gKdnZ2d@speakeasy.net>
jcipar  <jcipar@gmail.com> wrote:
+---------------
| I'm trying to run an external program and connect to its inputs and
| outputs.  I can run simple programs like "ls" where there is only
| output, but I can't get the input to work.
...
| And I am trying to run it with this:
| (defun run-test-program ()
|   (run-program "/home/jim/test"
| 	       '() :wait nil :input :stream :output :stream))
| (defvar *test-process* (run-test-program))
| 
| I can read the first line of output like this:
| (read-line (process-output *test-process*))
| 
| And, judging by the manual, I should be able to write like this:
| (write-line "jim" (process-input *test-process*))
| 
| But after doing so, subsequent read-line calls will just hang. ...
+---------------

I was able to duplicate your problem using CMUCL[1], and was
able to fix it by adding a FORCE-OUTPUT after the WRITE-LINE:

    cmu> (defvar *test-process* (run-test-program))

    *TEST-PROCESS*
    cmu> (read-line (process-output *test-process*))

    "I'm a computer, what is your name?"
    NIL
    cmu> (write-line "jim" (process-input *test-process*))

    "jim"
    cmu> (force-output (process-input *test-process*))

    NIL
    cmu> (read-line (process-output *test-process*))

    "well hello, jim, have a good day"
    NIL
    cmu> 

Here is the key hint:

    cmu> (describe (process-input *test-process*))

    #<Stream for descriptor 6> is a structure of type FD-STREAM.
    IN-BUFFER: NIL.
    ...
    OUT: #<Function LISP::OUTPUT-CHAR-FULL-BUFFERED {104E7DF1}>.
    ...
    ELEMENT-SIZE: 1.
    ELEMENT-TYPE: CHARACTER.
    FD: 6.
    BUFFERING: :FULL.
    ...
    OBUF-LENGTH: 4096.
    ...
    cmu> 

Apparently, RUN-PROGRAM creates its PROCESS-INPUT streams with
:BUFFERING :FULL by default, rather than :BUFFERING :LINE
(which is usually the default for streams going to a terminal).
Unlike output streams with :BUFFERING :LINE, output streams with
:BUFFERING :FULL are *not* automatically flushed just because
you write a newline, so you need to do an explicit FORCE-OUTPUT
to push the data out to the child process.


-Rob

[1] Yes, as others have reminded me quite forcefully, SBCL has
    diverged very significantly since its fork from CMUCL, and
    one should not assume that such details still carry over.
    But since in this case I was able to exactly duplicate your
    problem, there is a very good chance the fix is the same as well.

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607