[MLton] Re: [MLton-commit] r6699

Matthew Fluet fluet at tti-c.org
Tue Jun 16 08:36:33 PDT 2009


On Tue, 16 Jun 2009, Wesley W. Terpstra wrote:
> On Tue, Jun 16, 2009 at 1:13 AM, Matthew Fluet<fluet at tti-c.org> wrote:
>> So, I don't see why it is sensible for Cygwin
>> or MinGW to munge/unmunge arguments at all, since it can't know what
>> was/will-be done on the other end.
>
> Well, I won't debate whether it's sensible, but that is how it works.
> It does seem likely that the string eventually delivered to a
> CreateProcess kernel call is escaped similarly for both cygwin and
> mingw (though as I mentioned, it is possible this is false).

O.k., then what is the rationale for the Basis Library implementation to 
add another level of munging on top of that done by Cygwin or MinGW?

> I wouldn't be surprised if the spawn() function on cygwin1.dll
> requires no escaping at all. They're in a position to fix this bug for
> their applications.

My testing seems to support this claim.  The 
<src>/regression/args-spawn.sml test (renamed from spawn.sml and using 
CommandLine.name() to fetch the executable name) works fine, including 
when run from a path with spaces and when invoked with a full path (with 
spaces).

Of course, this is using a Cygwin program to spawn a Cygwin program (that 
happens to be itself); I'm not sure whether this configuration is meant to 
support a Cygwin program spawning a Windows CRT program?  It seems to:

[fluet at winxp-cygwin tmp]$ cat args-spawn.sml
val cmd = CommandLine.name ()
val _ = print (concat ["cmd: ", cmd, "\n"])
val args = CommandLine.arguments ()
val _ = foldl (fn (arg,()) => print (concat ["arg: ", arg, "\n"])) () args

open Posix.Process
open MLton.Process
val () =
    let
       val pid = spawn {path = hd args, args = args}
       val status = waitpid (W_CHILD pid, [])
    in
       ()
    end
[fluet at winxp-cygwin tmp]$ ./args-spawn C:\\Documents\ and\ Settings\\fluet\\My\ Documents\\My\ Programs\\finger.exe -l fluet at ttic.uchicago.edu
cmd: ./args-spawn
arg: C:\Documents and Settings\fluet\My Documents\My Programs\finger.exe
arg: -l
arg: fluet at ttic.uchicago.edu
[nagoya.uchicago.edu]

> Finger: connect::Connection refused
[fluet at winxp-cygwin tmp]$ ./args-spawn /cygdrive/c/Documents\ and\ Settings/fluet/My\ Documents/My\ Programs/finger.exe -l fluet at ttic.uchicago.edu
cmd: ./args-spawn arg: /cygdrive/c/Documents and Settings/fluet/My Documents/My Programs/finger.exe
arg: -l
arg: fluet at ttic.uchicago.edu
[nagoya.uchicago.edu]

> Finger: connect::Connection refused
[fluet at winxp-cygwin tmp]$ ./args-spawn /cygdrive/c/Documents\ and\ Settings/fluet/My\ Documents/My\ Programs/finger.exe '-l fluet at ttic.uchicago.edu'
cmd: ./args-spawn arg: /cygdrive/c/Documents and Settings/fluet/My Documents/My Programs/finger.exe
arg: -l fluet at ttic.uchicago.edu

Displays information about a user on a specified system running the
Finger service. Output varies based on the remote system.

FINGER [-l] [user]@host [...]

   -l        Displays information in long list format.
   user      Specifies the user you want information about. Omit the user
             parameter to display information about all users on the
             specifed host.
   @host     Specifies the server on the remote system whose users you
             want information about.

Note that in the last case, the single argument with an embedded space is 
delivered whole to the program, prompting the help listing that is given 
on any invalid argument.  I also note that the invoked program executes 
whether I use finger.exe or finger.  This would appear to be handled by 
the cygwin1.dll implementation of spawne, since the ML string is passed 
unmodified through to the spawne function.

This seems like reasonable behavior for MLton.Process.spawn{,e,p}.

> The CreateProcess will definitely need some sort
> of escaping, though.

Ok, because the CreateProcess function takes a single string for the 
arguments, so the munging needs to be done on the ML side.  And, the 
current claim is that the "default" munging for Cygwin, MinGW, and 
(normal) Windows CRT are all different? Or, rather, that there is no 
"standard" munging?

In any case, there seems to be a problem with CreateProcess, possibly 
independent of the argument munging.  The child process seems to to be 
created:

[fluet at winxp-cygwin tmp]$ cat args-create.sml
val cmd = CommandLine.name ()
val _ = print (concat ["cmd: ", cmd, "\n"])
val args = CommandLine.arguments ()
val _ = foldl (fn (arg,()) => print (concat ["arg: ", arg, "\n"])) () args

open MLton.Process
val () =
    let
       val pid =
          create {args = tl args,
                  env = NONE,
                  path = hd args,
                  stderr = Param.self,
                  stdin = Param.self,
                  stdout = Param.self}
       val status = reap pid
    in
       ()
    end
[fluet at winxp-cygwin tmp]$ ./args-create 'C:\WINDOWS\system32\finger.exe'
cmd: ./args-create
arg: C:\WINDOWS\system32\finger.exe
unhandled exception: SysErr: No child processes [child]



More information about the MLton mailing list