[plt-scheme] writing to subprocess's stdin and then...
I have been through the same topic. First I tried to just pass #f to
subprocess, and as Eli said, if the process write too much data,
deadlock happens. Then I also noticed that file-port instead of a normal
port, so my final code looks like:
(let ((f2 (make-temporary-file)))
(let-values (((process dummy stdin stderr)
(subprocess (open-output-file f2 'replace)
#f #f
"command line"
)))
(subprocess-wait process)
(close-output-port stdin)
(unless (eof-object? (read stderr))
(error (read-line stderr)))
(close-input-port stderr))
(let ((stdout (open-input-file f2)))
(read stdout)
Hope that helps.
Chongkai
Andrew Reilly wrote:
> Hi Eli,
>
> I'm glad that this topic came up, because I was playing with just
> these issues last weekend. I had been using process rather than
> subprocess (so I had to make up some amusing string quoting to
> pass in complicated, space-containing file names), and it mostly
> worked, but I got the occasional hang, which I suspect was
> because of the blocking/deadlock issues that you mentioned.
>
> Anyway, I've just tried a variation on your version:
>
> On Tue, 17 Jun 2008 04:49:10 -0400
> Eli Barzilay <eli at barzilay.org> wrote:
>
>> Here's the revised example -- with no use of threads.
>>
>> | #lang scheme
>> |
>> | (require scheme/port)
>> | (define (with-input-from-subprocess exe thunk)
>> | (define-values (p pout pin perr)
>> | (subprocess #f #f (current-error-port)
>> | (find-executable-path exe)))
>> | (close-output-port pin)
>> | (parameterize ([current-input-port pout])
>> | (begin0 (thunk)
>> | (subprocess-wait p))))
>> |
>> | (with-input-from-subprocess "du"
>> | (lambda ()
>> | (for ([line (in-lines)])
>> | (printf ">> ~s\n" (regexp-split #rx"[/\t]" line)))))
>>
>
> Specifically, my version looks like:
>
> (define (with-input-from-subprocess thunk exe . args)
> (define-values (p pout pin perr)
> (apply subprocess (append (list #f #f (current-error-port)
> (find-executable-path exe))
> args)))
> (close-output-port pin)
> (parameterize ((current-input-port pout))
> (begin0 (thunk)
> (subprocess-wait p))))
>
> ; process individual tracks: do the real work
>
> (define (get-flac-meta file)
> (make-immutable-hash
> (with-input-from-subprocess
> (lambda ()
> (let all ()
> (match (read-line)
> ((regexp #rx"(.*)=(.*)" (list _ tag val)) (cons (cons tag val) (all)))
> (_ '()))))
> "metaflac" "--export-tags-to=-" (path->string file))))
>
> The problem is that this produces an error at run-time:
> subprocess: expects type <file-stream-output-port> as 3rd
> argument, given: #<output-port>; other arguments were: #f #f
> #<path:/usr/local/bin/metaflac> "--export-tags-to=-" "some file
> name..."
>
> Should subprocess really be so picky? I suppose that it has to
> be, because the unix process wants a real file descriptor. The
> current-error-port in this case is that of the drscheme
> environment. Seems to work OK from mzscheme on the command line.
>
> Cheers,
>
>