SBCL: Collect the output of the program execution process while running

Dear StackExchange Members,

I recently started discussing with Common Lisp and want to create a web interface to administer a modified Minecraft server. I already tried this solution , but in this case the function just hangs and never returns.

My code looks like this:

(defvar *proc*)

(defun create-minecraft-proc ()
  (let* ((binary "/usr/bin/java")
    (jar "/home/user/temp/Vanilla 1.8/minecraft.jar")
    (dir "/home/user/temp/Vanilla 1.8")
    (args (list "-jar" jar "nogui")))
    (setf *proc* (sb-ext:run-program binary args :directory dir :wait nil :input :stream :output :stream))))

(defun copy-stream (in out)
  (loop for line = (read-line in nil nil)
     while line
       do (write-line line out)))

(defun get-minecraft-output ()
  (with-open-stream (proc-stream (process-output *proc*))
    (with-output-to-string (out)
      (copy-stream (process-output *proc*) out)))

      

How can I get a line containing the full output of the process before that time without waiting for it to complete?

+3


source to share


1 answer


While experimenting with /bin/cat

, I have found some things that might help you.

First of all, always use finish-output

after writing to process input:

(format (process-input *cat*) "Hello~%")
(finish-output (process-input *cat*))

      

Otherwise, the input may not reach the subprocess until you close the input stream. If Minecraft requires input before it generates any output, then trying to read from its output without the required input will cause the SBCL to hang in a way that cannot be restored with Cc Cc in SLIME.



Second, use listen

to determine if any output has been produced:

(when (listen (process-output *cat*))
    (read-line (process-output *cat*)))

      

With finish-output

and listen

, I was able to avoid the hang when incrementally reading from stdout cat.

+4


source







All Articles