common lisp - How to read from large process output correctly -



common lisp - How to read from large process output correctly -

there few answers on how read process stream far can see not cover reading process which:

may run long time before making output makes huge output @ end of lifetime (more stream buffer can hold) should not run longer given time frame the resulted output needed whole (long character string)

therefore using mentioned solutions either result in wasted process cycles loop seek read stream though there no output, or non termination of solution process cannot print whole output (due total buffer) , output handler waits process termination prior reading.

my current solution looks (inspired solution mass reading big files)

(defun control-process (process timeout) (sb-ext:with-timeout timeout (handler-case (do ((output-stream (sb-ext:process-output process)) (string nil)) ((and (equalp (sb-ext:process-status process) :exited) (equalp (peek-char nil output-stream nil :eof) :eof)) (values string :exited)) (cond ((equalp (sb-ext:process-status process) :signaled) (error 'unexpected-process-finish :finish-status :signaled)) ((equalp (sb-ext:process-status process) :stopped) (error 'unexpected-process-finish :finish-status :stopped))) (let ((seq (make-string (file-length output-stream)))) (read-sequence seq output-stream) (setf string (concatenate 'string string seq)) (sleep 1))) (sb-ext:timeout (err) (declare (ignore err)) (values nil :timeout)) (unexpected-process-finish (err) (values nil (finish-status err))))))

the function called process:

(sb-ext:run-program "/path/to/programm" (list "--params" "foo" "bar") :output :stream :wait nil)

but solution has drawbacks:

it not work stream not associated file (error) it generic sleep of 1 though there might not output @ time it lot of concatenation seems inelegant solution

final handling/clean-up of exited/stopped/too long running process handled calling function.

how can read process which:

may run long time (and output @ end of lifetime) may create output larger stream buffer must not run longer given time span output needed whole

?

might string output stream work you? output stored in string afterward, buffering shouldn't much of problem. e.g.,

* (with-output-to-string (out) (sb-ext:run-program "/bin/ls" '("/") :output out)) "bin boot … vmlinuz vmlinuz.old "

if want preallocate string, can to, with-output-to-string's string-form argument.

you don't have utilize with-output-to-string utilize string-output-stream, though. create 1 make-string-output-stream , pass sb-ext:run-program. you'd text out of get-output-stream-string.

common-lisp sbcl

Comments