Common lisp 无法使输入流在SBCL sb ext:运行程序中工作
而以下工作:Common lisp 无法使输入流在SBCL sb ext:运行程序中工作,common-lisp,inputstream,sbcl,external-process,Common Lisp,Inputstream,Sbcl,External Process,而以下工作: (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)) 下面的代码没有-写入“001”后将停止: 所以它似乎在sbext:runprogram中默默地保留执行 这是Ubunt
(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))
下面的代码没有-写入“001”后将停止:
所以它似乎在sbext:runprogram
中默默地保留执行
这是Ubuntu 16.04.1上的SBCL 1.3.6
有什么想法吗?弗兰克,提前谢谢你,正如我在评论中提到的,问题在于
:WAIT T
参数。它会导致对SB-EXT:RUN-PROGRAM的调用在子进程退出之前不会返回
在第一个示例中,您将字符串输入流传递给子进程cat
将从流中读取输入,当输入结束时,将有文件结束,因此cat
退出。在第二个示例中,程序没有可用的输入,因此它实际上是一个无限循环(就像在命令行上运行cat
,不给它任何输入;它永远不会退出)
解决方案是使用:WAIT NIL
。您还必须使用close
关闭输入流,因为否则将没有EOF,并且cat
将继续侦听更多输入。关闭流后,您还需要使用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))
我不确定您为什么对子输出使用*TRACE-OUTPUT*
,因此我将其更改为*STANDARD-OUTPUT*
另外,使用格式
进行这样的调试有点难看。CommonLisp提供了实际的调试工具。在这种情况下,您可以使用:
这将使您进入调试器,显示下一步要计算的调用。您可以调用
STEP-NEXT
-restart继续下一个调用。这就是工作原理,如下所示:
:WAIT T
表示等待进程退出。:WAIT T
在两种情况下都存在,在工作情况下也存在,因此这不能作为解释。问题也不在于sb:ext-run-program
正在离开它自己的执行,整个let
blog没有运行显示任何日志输出-即使使用:wait-nil
,也不会出现这种情况。无论如何,谢谢你,在第一种情况下,你给它一个字符串输入流cat
读取输入,直到其EOFs,然后返回。在第二个示例中,您没有向流写入任何内容,因此不会出现EOF,并且cat
将永远等待更多输入。好的-再次感谢。我明白你的观点,现在将集中讨论主要问题。这里我不明白的是:对于第二个例子,我确实为流程提供了输入,并且我完成了/刷新了输入流——这两个操作都是通过streams
完成的。我也感到困惑,因为Emacs/Slime没有阻止等待过程,所以REPL仍然是响应的。在SBCL REPL中进行测试时,等待过程实际上会阻塞。不管怎样,我按照你的建议尝试了等待nil
,然后。。。成功了;)所以我仍然不能完全理解它,但我有一个解决方案——再次感谢。@FrankRuben Emacs/Slime使用不同的线程。REPL使用自己的线程,而其他任务则使用“工作”线程执行。使用slime list线程来列出它们。当您自己运行SBCL时,您只与单个线程进行交互。您可以使用sb-thread:make-thread启动另一个线程,结果将与您在Emacs中观察到的结果相似。
(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))
(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)))
(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))