sionescu / iolib

Common Lisp I/O library
http://common-lisp.net/project/iolib/
MIT License
141 stars 31 forks source link

Added failing (hanging) test for RUN-PROGRAM. #29

Open attila-lendvai opened 9 years ago

attila-lendvai commented 9 years ago

unfortunately unix only, i cannot test on windows.

attila-lendvai commented 9 years ago

unfortunately this test in its current form is not too travis friendly, because it hangs... :/

attila-lendvai commented 9 years ago

@fare you may want to check this out if it's relevant for the run-program code in UIOP.

fare commented 9 years ago

Well, iolib has its own run-program, independent from uiop's. UIOP's run-program isn't geared for asynchronous / non-blocking calls (except that on some implementations it uses such a call underneath).

attila-lendvai commented 9 years ago

@fare the issue is when using pipes:

   ;; As of this writing the following call will hang. The reason is that RUN-PROGRAM
   ;; tries to fully read the stdout pipe without simultaneously reading stderr, but
   ;; this invocation only writes to stderr and thus eventually overfills the stderr pipe.

    (iolib.os:run-program args :stdin :pipe :stdout :pipe :external-format :iso-8859-1)

but now that i think about it, if this bug exists somewhere else, then it's in the CL implementations's run-program, not in UIOP, that merely wraps them. sorry for the noise.

attila-lendvai commented 9 years ago

FTR, on sbcl this runs as expected:

(read (sb-ext:process-output (sb-ext:run-program "/bin/sh" (list "-c" "echo alma") :output :stream)))

but this hangs:

(sb-ext:run-program "/bin/sh" (list "-c" "/bin/cat /bin/sh") :output :stream)
fare commented 9 years ago

Well, if the lisp program doesn't drain the pipe, of course pipe will block after a short while.

attila-lendvai commented 9 years ago

FTR, sbcl has a :wait nil arg for this.

sionescu commented 9 years ago

SBCL's :wait nil causes RUN-PROGRAM to return immediately. For that IOlib has CREATE-PROCESS, which also supports a few more features wrt. FD indirections. RUN-PROGRAM is intended to be for simple synchronous uses.

sionescu commented 9 years ago

That said, you're right that the draining of the two pipes should occur simultaneously, so I'll use a simple poll() event-loop. That ought to be fairly portable.

fare commented 9 years ago

Yeah, that's why uiop:run-program uses only one pipe at most, and redirects the other stream (if any) to a file — that's the only way to work synchronously that's portable.