[racket] Duplicating output from a system call

From: Robby Findler (robby at eecs.northwestern.edu)
Date: Thu May 16 20:43:58 EDT 2013

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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20130516/1c4a93ac/attachment-0001.html>

Posted on the users mailing list.