Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re^3: exec always invokes the shell? win32

by ELISHEVA (Prior)
on Feb 10, 2011 at 17:20 UTC ( #887502=note: print w/ replies, xml ) Need Help??


in reply to Re^2: exec always invokes the shell? win32
in thread exec always invokes the shell? win32

It may not exactly be that cmd.exe is being called. What you are more likely seeing is a side effect of the way programs need to pass arguments to MS-Win programs. A similar issue (parameter list mangling) was seen recently when someone ran into problems passing parameters from Java to Perl with a system call. He too was passing a list.

The issue is this: MS-Windows programs don't actually get lists when they are called by Ms-Win. They expect to get a single string (lpCmdLine). Programs usually have some internal code that converts that string back into an array. In order to play nicely with that code, Java (and I now suspect Perl) takes your list and concatenates it into a string before passing it. The program (in this case Perl) then splits it back into arguments and viola.

For some in depth discussion about why there just aren't any good choices in this matter, see http://bugs.sun.com/view_bug.do?bug_id=4064116. You might also want to look at these two posts on the Java/Perl thread: Re^9: Running perl from java and Re^8: Running perl from java or the thread as a whole.


Comment on Re^3: exec always invokes the shell? win32
Re^4: exec always invokes the shell? win32
by Anonymous Monk on Feb 10, 2011 at 18:04 UTC
    Then how come system doesn't have the same problem?

    I appreciate you trying to help, but sorry, you simply have no idea what you're talking about

      The question "why is exec splitting "1 2" into "1" and "2", but system does not is a good question. The conclusion that exec always calls the shell is not.

      Quite simply, your theory is counter to the Perl documentation and the intent of both system and exec. Neither exec nor system call the shell except possibly in the case that someone tries to exec a shell built-in. If you want the shell invoked, you use backticks. exec and system use native systems calls whenever possible.

      In the case of Ms-Win, exec first tries a direct call on the program via CreateProcess. The shell is only invoked if this calls fails or certain internal Perl limits on the number of wait objects are reached.. Both exec and system use the same code. The only difference between the two is a single mode code (P_WAIT vs. P_NOWAIT). This does not affect parameter handling. You can confirm this yourself by looking at the source code yourself.

      As regards parameter mangling. CreateProcess takes a string, not an array, so Perl collapses your arguments into a single string. (Confirmed by source diving). What actually happens after that depends on the how the receiving program chooses to parse the command line string.

      As for the differences in their behavior, based on reading the Perl source code, I see two possibilities:

      • system did not fail and exec did. Hence one went through cmd.exe and the other did not. There are two possible causes for failure. Inside Perl, there is a maximum limit on the number of wait objects. This affects exec but not system. However, unless your perl is compiled with very low limit (0?) that isn't likely going to be an issue in your script. Outside Perl in the Ms-Windows environment, you'd have to look for some sort of resource allocation problem that affects exec'd processes but not waited upon processes.

      • You are using a perl compiled from a different codebase than the one I'm looking at. The codebase linked to above is the main Perl codebase. However, there is more than one MsWin codebase for Perl (Active State, for instance, uses some of its own proprietary sources). Or perhaps you are working with an older release of an open source version of Perl.

      Finally, you should know that not all platforms get the results you did. The behavior I get running your script on a Linux box does not show any difference between system and exec. "1 2" does not split into two parameters (hardly surprising since linux takes an parameter array not a command line string). Also I get the reverse behavior you do: no args has no output, 1 arg has output:

      $ perl Anony.pl perl -l -e "print for @ARGV" -- 1 2 system at Anony.pl line 19. exec at Anony.pl line 22. $ perl Anony.pm 1 perl -l -e print for @ARGV 1 2 system at Anony.pl line 19. 1 2 exec at Anony.pl line 22. 1 2

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://887502]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (6)
As of 2014-07-14 00:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    When choosing user names for websites, I prefer to use:








    Results (253 votes), past polls