简体   繁体   English

无法在SBCL sb-ext:run-program中获取输入流

[英]Cannot get input stream working in SBCL sb-ext:run-program

While the following works: 虽然以下工作:

(let* ((i (make-string-input-stream "foo bar baz"))
       (p (sb-ext:run-program "/bin/cat" '() 
              :input i :output *trace-output* :wait t)))
  (sb-ext:process-close p))

the code below does not - it will stop after writing "001": 下面的代码没有 - 它会在写“001”后停止:

(let* ((_1 (format t "001~%"))
       (p (sb-ext:run-program "/bin/cat" '() 
              :input :stream :output *trace-output* :wait t))
       (_2 (format t "010~s~%" p))
       (s (sb-ext:process-input p)))
  (declare (ignore _1 _2))
  (format s "foo bar baz~%")
  (finish-output s)
  (sb-ext:process-close p))

So it seems to silently leave execution in sb-ext:run-program . 所以它似乎默默地将执行留在sb-ext:run-program

This is with SBCL 1.3.6 on Ubuntu 16.04.1. 这与Ubuntu 16.04.1上的SBCL 1.3.6有关。

Any ideas? 有任何想法吗? Thanks in advance, Frank 先谢谢你,弗兰克

As I mentioned in the comments, the problem is the :WAIT T argument. 正如我在评论中提到的,问题是:WAIT T参数。 It causes the call to SB-EXT:RUN-PROGRAM to not return until the child process exits. 它导致调用SB-EXT:RUN-PROGRAM在子进程退出之前不返回。

In the first example you passed a string input stream to the child process. 在第一个示例中,您将字符串输入流传递给子进程。 cat will read input from the stream, and when the input ends there will be a End of File, so cat exits. cat将从流中读取输入,当输入结束时将出现文件结束,因此cat退出。 In the second example there is no input available for the program, so it's effectively an infinite loop (just like if you run cat on the command line, and don't give any input to it; it will never exit). 在第二个例子中,程序没有可用的输入,所以它实际上是一个无限循环(就像你在命令行上运行cat ,并且不给它任何输入;它永远不会退出)。

The solution is to use :WAIT NIL . 解决方案是使用:WAIT NIL You will also have to close the input stream with CLOSE , because otherwise there will be no EOF and cat keeps listening for more input. 您还必须使用CLOSE输入流,否则将不会有EOF并且cat会继续侦听更多输入。 You'll also want to use SB-EXT:PROCESS-WAIT after closing the stream to wait for cat to exit itself. 关闭流后,您还需要使用SB-EXT:PROCESS-WAIT等待cat退出。

(let* ((p (sb-ext:run-program "/bin/cat" '() 
                              :input :stream
                              :output *standard-output*
                              :wait nil))
       (s (sb-ext:process-input p)))
  (format s "foo bar baz~%")
  (finish-output s)
  (close s)
  (sb-ext:process-wait p)
  (sb-ext:process-close p))

I'm not sure why you used *TRACE-OUTPUT* for the child output, so I changed it to *STANDARD-OUTPUT* . 我不确定为什么你使用*TRACE-OUTPUT*作为子输出,所以我将它改为*STANDARD-OUTPUT*

Also, using FORMAT for debugging like that is kind of ugly. 另外,使用FORMAT进行调试就好了。 Common Lisp provides actual debugging tools. Common Lisp提供实际的调试工具。 In this case you could use STEP : 在这种情况下,您可以使用STEP

(step (let* ((p (sb-ext:run-program "/bin/cat" '() 
                                    :input :stream
                                    :output *standard-output*
                                    :wait nil))
             (s (sb-ext:process-input p)))
        (format s "foo bar baz~%")
        (finish-output s)
        (close s)
        (sb-ext:process-wait p)
        (sb-ext:process-close p)))

This will put you in the debugger, showing the call being evaluated next. 这将使您进入调试器,显示接下来要评估的调用。 You can invoke the STEP-NEXT -restart to continue to the next call. 您可以调用STEP-NEXT -restart继续下一个呼叫。

This is what works, as suggested by jkiiski : 正如jkiiski所建议的那样 ,这是有效的

(let* ((p (sb-ext:run-program "/bin/cat" '() 
                              :input :stream 
                              :output *standard-output* 
                              :wait nil))
       (s (sb-ext:process-input p)))
  (format s "foo bar baz~%")
  (finish-output s)
  (sb-ext:process-wait p)
  (sb-ext:process-close p))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM