[squeak-dev] OSProcess streaming and early termination

David T. Lewis lewis at mail.msen.com
Tue Dec 11 16:56:36 UTC 2012


On Mon, Dec 10, 2012 at 05:35:06PM +0100, Bert Freudenberg wrote:
> 
> On 2012-12-08, at 17:51, "David T. Lewis" <lewis at mail.msen.com> wrote:
> 
> > On Sat, Dec 08, 2012 at 10:55:41AM -0500, David T. Lewis wrote:
> >> On Sat, Dec 08, 2012 at 09:16:46AM +0100, Bert Freudenberg wrote:
> >>> On 08.12.2012, at 03:10, "David T. Lewis" <lewis at mail.msen.com> wrote:
> >>>> 
> >>>> cmd := 'od -v -t x1 ', (Smalltalk imageName copyAfterLast: $/) asVmPathName.
> >>>> pipeline := ProxyPipeline command: cmd.
> >>>> data := pipeline next: 1000.
> >>>> pipeline closePipes.
> >>>> data inspect
> >>> 
> >>> Okay, that looks a lot simpler. But with the string interface I have to worry about argument escaping. That's why I wanted to use the array interface, and avoid a shell. Constructing a sanitized string from user data is very hard, and made unnecessary bybusing a non-interpreted interface.
> >>> 
> >>> Also, as I wrote I need to be able to set the working directory (and potentially the environment). Your example only works accidentally because you launched squeak from the image directory.
> >>> 
> >> 
> >> This does not directly answer your question, but here is a way to
> >> evaluate the command in a specified directory:
> >> 
> >>  file := 'squeak'.
> >>  path := '/usr/local/bin'.
> >>  cs := CommandShell new workingDirectory: path.
> >>  cmd := 'od -v -t x1 ', file.
> >>  pipeline := ProxyPipeline command: cmd shell: cs.
> >>  data := pipeline next: 50.
> >>  pipeline closePipes.
> >>  data ==> '0000000 23 21 2f 62 69 6e 2f 73 68 0a 23 20 0a 23 '
> >>  pipeline errorUpToEnd ==> ''
> >> 
> >> Or the same thing with file not found in that directory:
> >> 
> >>  file := 'noSuchFile'.
> >>  path := '/usr/local/bin'.
> >>  cs := CommandShell new workingDirectory: path.
> >>  cmd := 'od -v -t x1 ', file.
> >>  pipeline := ProxyPipeline command: cmd shell: cs.
> >>  data := pipeline next: 50.
> >>  pipeline closePipes.
> >>  data ==> ''
> >>  pipeline errorUpToEnd ==> '/usr/bin/od: noSuchFile: No such file or directory
> >>  '
> >> 
> > 
> > And if you will forgive yet another answer to the question that you
> > did not ask, here is a way to set an environment variable:
> > 
> >  cs := CommandShell new workingDirectory: '/usr/local/bin'.
> >  cs environment at: #FOO put: 'BAR'.
> >  cmd := '/usr/bin/env | grep FOO'.
> >  pipeline := ProxyPipeline command: cmd shell: cs.
> >  data := pipeline upToEndOfFile.
> >  pipeline closePipes.
> >  data ==> 'FOO=BAR
> >  '
> > 
> > Dave
> 
> 
> Okay. It sounds like you're strongly advocating to use CommandShell, which means I will have to escape my filenames and hope for the best. How much interpretation is going on in the shell? How do I predict which shell will be used? 
> 

CommandShell does not use any unix shell at all. Instead, it implements a
crude approximation of a shell with all the syntax parsing and file globbing
done in Smalltalk. One of the things that is not implemented is quoting of
strings in the command line, which is a problem if you need to pass an argument
that contains a space character.

However, I found a workaround for the problem, which is to use xargs to
to the parsing. This is a snippet from a script that I'm working on to do
Cog VM builds:

  configCommand := '../platforms/unix/config/configure'.
  configArgs := 'CC="gcc -m32" LDFLAGS="-m32" CFLAGS="-m32 -g -O2 -msse2',
          ' -D_GNU_SOURCE -DNDEBUG -DITIMER_HEARTBEAT=1 -DNO_VM_PROFILE=1',
          ' -DCOGMTVM=0 -DDEBUGVM=0" LIBS=-lpthread'.

  shell := CommandShell new.
  shell command: 'mkdir build'.
  shell command: 'cd build'.
  shell command: 'echo ', configArgs, ' | xargs ', configCommand.

I wish I had a better answer to your original question of how to do it
more easily with PipeableOSProcess directly, but I don't :(   However,
the ProxyPipeline approach does work, and it has the advantage of taking
care of the housekeeping chores such as cleaning up open file handles and
making sure that you don't accidentally block your VM on a pipe read
operation. The disadvantage is that it forces you to use the simulated
shell (CommandShell) rather than the a real one.

Dave



More information about the Squeak-dev mailing list