2016-08-07 6 views
1

を、次の作品中:はSBCL SB-EXTで働く入力ストリームを取得できません:実行プログラム

(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" を書いた後、停止します。

(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)) 

それでは、黙ってsb-ext:run-programに実行を残しているようです。

これは、Ubuntu 16.04.1のSBCL 1.3.6と同じです。

アイデア?事前に感謝、フランク

+2

':T 'は、プロセスが終了するまで待つ意味WAIT。 – jkiiski

+0

':T 'が作業の場合にも、両方のケースであり待って - そう、これは説明することはできません。また、 'sb:ext-run-program'が独自の実行を残しているという問題ではなく、' let'ブログ全体がログ出力を表示せずに残っ​​ています - これは ':wait nil'でも期待されません。とにかくありがとう、 –

+1

最初のケースでは、それに文字列入力ストリームを与えています。 'cat'はEOFまで入力を読み込んでから復帰します。 2番目の例ではストリームに何も書き込んでいないので、EOFは存在しません。また、 'cat'はより多くの入力を永久に待っています。 – jkiiski

答えて

3

私がコメントで述べたように、問題は:WAIT T引数です。子プロセスが終了するまで、SB-EXT:RUN-PROGRAMへの呼び出しは返されません。

最初の例では、文字列入力ストリームを子プロセスに渡しました。 catはストリームから入力を読み込み、入力が終了するとファイルの終わりがあるので、catが終了します。 2番目の例では、プログラムに利用できる入力がないので、事実上無限ループです(コマンドラインでcatを実行した場合と全く同じように、入力を与えずに終了しません)。

解決策は、:WAIT NILを使用することです。 CLOSEで入力ストリームを閉じる必要があります。そうしないとEOFはなくなり、catは入力を継続して聞き続けます。 catが終了するまでストリームを閉じた後にSB-EXT:PROCESS-WAITを使用することもできます。

(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*にそれを変更しました。

また、デバッグのためにFORMATを使用すると、醜いものになります。 Common Lispは実際のデバッグツールを提供します。この場合、あなたは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))) 

これは次評価されているコールを示す、デバッガであなたを配置します。 STEP-NEXT -restartを呼び出して、次の呼び出しを続けることができます。

+0

OK - ありがとうございます。私はあなたのポイントを得て、今主な問題に集中します。私がここで理解できないことは、2番目の例でも、プロセスの入力を提供し、その入力ストリームを終了/フラッシュします。両方のアクションはストリーム 's'を介して実行されます。 Emacs/Slimeは待機プロセスをブロックしないので、私も混乱しました.REPLはまだ応答しています。 SBCL REPLでテストする場合、待機プロセスは実際にブロックされます。とにかく、あなたが提案した通りに待っているのをやめてみました...それは働いていました;だから私はまだ完全には解決しませんが、解決策があります。 –

+0

@FrankRuben Emacs/Slimeは異なるスレッドを使用します。 REPLは独自のスレッドを使用しますが、他のタスクは「ワーカー」スレッドを使用して実行されます。それらを一覧表示するにはslime-list-threadsを使用します。あなた自身でSBCLを実行すると、あなたはただ1つのスレッドと対話しているだけです。あなたはsb-thread:make-threadを使って別のものを起動することができ、その結果はEmacs内での観察と似ています。 – coredump

0

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)) 
関連する問題