[racket] Embedding multiline shell scipts

From: Neil Van Dyke (neil at neilvandyke.org)
Date: Sun Feb 6 11:16:00 EST 2011

Thomas Chust wrote at 02/06/2011 10:14 AM:
> 2011/2/6 Manfred Lotz <manfred.lotz at arcor.de>:
>   
>> [...]
>> I don't know how to merge stdout and stderr in proper sequence.
>> [...]
>>     
>
> There is no such thing as proper sequencing of data flowing through different streams.
>
> Due to buffering in system libraries and the operating system kernel it is also entirely impossible to reliably process the output data in the exact sequence it was produced by the external process.

Agreed with Thomas that doing this perfectly is impossible in the 
general case, even when there's a single-threaded producer of the two 
streams.

However, if you want to sequence reading stdout and stderr close enough 
for most purposes, keep in mind that these are usually interleaved at 
the resolution of lines rather than characters, so you can get this 
pretty much right, and still do fairly efficient block reads.  So, you 
can do the sequencing efficiently in your reading process by doing raw 
stdio and avoiding any buffering port abstractions in your library, 
doing a "sync" loop on the ports, and implementing your own buffering 
for each port, out of which buffer you pick a complete line at a time.  
You also can tweak this to better interleave reads from the two 
streams/buffers.  You can also use time or other heuristics to detect 
when, say, a stdout message like "Processing..." without newline should 
be handled because it was interrupted by a subsequent stderr error 
message.  There might still be buffering outside of your control, but I 
think it doesn't often matter.

Once you get into "expect"-like interaction with a process using the 
three streams at once, and doing pattern-matching while also capturing 
the output, and doing this all efficiently, it's tricky.  There's no 
reason that a generalized library routine to do this can't be 
implemented in Racket, but I'm not aware of one.  If you hand-implement 
for a particular purpose, I think you'll be getting your hands dirty 
with "sync", your own buffering of both input and output, block I/O, and 
some strategy for how to do your pattern-matching efficiently on the 
buffers.  IMHO, this should feel like systems programming if you're 
doing it efficiently.  This complication does not reflect a limitation 
of Racket, but instead that Racket is flexible enough that this doing 
this complicated stuff is possible.

-- 
http://www.neilvandyke.org/

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20110206/8f0fa856/attachment.html>

Posted on the users mailing list.