[racket] Duplicating output from a system call

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Thu May 16 23:09:23 EDT 2013

I'm showing up late to this party, but...

DrDr has to do this in a very reliable way and it is abstracted into a
fairly nice function called run/collect/wait

https://github.com/plt/racket/blob/master/collects/meta/drdr/run-collect.rkt

You may want to look at it a little.

Jay

On Thu, May 16, 2013 at 6:43 PM, Robby Findler
<robby at eecs.northwestern.edu> wrote:
> Oh, I meant to say that I think that process*/ports can make things easier
> than system for this kind of thing. read-string-evt is more for if you want
> to get good performance for high-throughput streams, which it seems like
> isn't an issue here. This different seems unlikely to help with whatever is
> going wrong.
>
> I don't see that you're closing the ports anywhere, so maybe there is
> something like that happening in your real script. Make sure that you close
> everything as soon as you know there is no more data. Otherwise, I'm just
> not sure what's going wrong.
>
> As for process* and system*: they will work, I think, unless the strings you
> put in the "~a"s are multiple arguments and you can't do that parsing
> yourself. You'd do something like
>
>   (system* "/usr/bin/instruments" "-t" (path->string instruments-path)
> (path->string app-path) "-e" "UIASCRIPT" (path->string script-path))
>
> roughly.
>
> Robby
>
>
> On Thu, May 16, 2013 at 7:27 PM, Nick Shelley <nickmshelley at gmail.com>
> wrote:
>>
>> I tried "file-stream-buffer-mode" on the stdout port and that didn't help.
>> That seems to be the only port that will work with that method.
>>
>> I also realize I misled you when I put "<script-that-logs-to-console>" as
>> a placeholder in the code. Really it is a command of the form (format
>> "instruments -t ~a \"~a\" -e UIASCRIPT ~a" ...) where two of the three ~a
>> arguments are passed to Racket through the command-line. If I understand
>> correctly, process* and system* won't work with this form.
>>
>> After experimenting a bunch unsuccessfully, I tried putting the system
>> call before I created the ports and without a parameterized
>> current-output-port. The results I see are that for the first system call I
>> get real-time logs to the console, then with the next one the tests repeat,
>> but the logs don't come until the end.
>>
>> I even tried Neil's suggested approach in case that made a difference.
>> Aside from the fact that it has the same buffering problem, I never get the
>> eof event, so I don't know when to terminate the sync loop. Here's the code:
>>
>>   (define-values (in out) (make-pipe))
>>   (define stdout (current-output-port))
>>   (define string-port (open-output-string))
>>   (process/ports out #f #f (format "instruments -t ~a \"~a\" -e UIASCRIPT
>> ~a" instruments-path app-path script-path))
>>   (let loop ([data (sync (read-string-evt 1 in))])
>>     (unless (eof-object? data)
>>       (display (format "data: [~a]" data) stdout)
>>       (display data string-port)
>>       (loop (sync (read-string-evt 1 in)))))
>>   (printf "~n~nresults: ~a~n" (get-output-string string-port))
>>
>> With this I get the delayed logs (each letter in brackets per sync event)
>> and then the program hangs waiting for an eof that never comes. Out of
>> curiosity, why did both of you recommend this approach over the system
>> approach? Either I'm doing it completely wrong or I just can't see the
>> advantage.
>>
>>
>> On Thu, May 16, 2013 at 5:08 PM, Neil Van Dyke <neil at neilvandyke.org>
>> wrote:
>>>
>>> You can try "file-stream-buffer-mode" on the port.
>>>
>>> Neil V.
>>>
>>
>>
>> ____________________
>>   Racket Users list:
>>   http://lists.racket-lang.org/users
>>
>
>
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users
>



-- 
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

"The glory of God is Intelligence" - D&C 93

Posted on the users mailing list.