in reply to system and $?

rovf,
The most interesting thing to me isn't that you didn't get a -1 on any of those platforms but that Solaris gave you a 0. That means the program executed successfully - which you claim is impossible. According to the same docs, there are two reasons you might get a -1.

Return value of -1 indicates a failure to start the program or an error of the wait(2) system call (inspect $! for the reason).

You haven't mentioned what $! says but I am at a loss to explain your observed behavior. I typically need to bitshift $? to get the true exit code ($? >> 8) but that obviously does nothing for you here.

Cheers - L~R

Replies are listed 'Best First'.
Re^2: system and $?
by rovf (Priest) on Aug 26, 2009 at 12:49 UTC
    You haven't mentioned what $! say

    In this posting, I was mainly interested why system() does not adhere to the docs in that it does not return -1 on some platforms even the execution failed.

    But - and maybe I should have mentioned this in my original post - the interest in this issue arose from a discussion with a co-worker about the proper usage of $!. My co-worker argued that it is never necessary to explicitly set $!=0 in a Perl program. His argument sounded convincing: $! (which is just errno) is only set if a low-level system call encounters a problem; otherwise, the value is not changed. Therefore, his argument goes, we first need to check if a function was successful, and only if it is not, we investigate $!. Example:

    if(open(FOO,'<',$foo)) { ... } else { print "open $foo: $!\n"; }
    This sounded convincing, but for the safe side, I tried to find a counter example, and came up with the example of system('myprog.exe'), where I can't, without prior setting of $!=0, reliably distinguish, whether or not myprog.exe has been executed with an exit code of 1, or could not be executed because it does not exist:

    If myprog.exe can not be run, system(...) returns on my platform 256 (which is exit code 1, no child-error), and, as you point out, sets $! to some error code. But if myprog.exe can be run, and exits with code 1, I also get 256 as return code, and $! has an undefined value (it is set to whatever it had been set before the call to system). Only by explicitly setting it to 0 prior to running system(), is it that I can distinguish between those cases.

    -- 
    Ronald Fischer <ynnor@mm.st>
      rovf,
      I have never set $! in a program to set the exit status - I have always used exit for that.
      #!/usr/bin/perl # ... rest of program exit(0); # assuming everything went according to plan
      Does that not work on windows?

      Cheers - L~R

        I have never set $! in a program to set the exit status
        Of course you don't set $! to set the exit status!! You set $! to zero before a call to system(), in order to clear it. If system returns no error, but $! is set afterwards, you know that there must have been an error indeed. If you would not clear $! before the call to system(), you would not know afterwards whether there was an error in system(), or in some earlier function. For example, in the two following cases (on my platform), system returns the same value in both cases, and $! is also set in both cases, although only the first system() call actually failed:

        # On Windows 2000, ActiveState Perl 5.8.8 or 5.10 # case one: opendir(FOO,'.'); system('this_program_does_not_exist'); # $? == 256, $! != 0 # case two: opendir(BAR,'this_directory_does_not_exist'); system('perl -e "exit 1"'); # $? == 256, $! != 0
        But if you explicitly reset $!, you can distinguish between those cases:
        # On Windows 2000, ActiveState Perl 5.8.8 or 5.10 # case one: opendir(FOO,'.'); $!=0; system('this_program_does_not_exist'); # $? == 256, $! != 0 # case two: opendir(BAR,'this_directory_does_not_exist'); $!=0; system('perl -e "exit 1"'); # $? == 256, $! == 0

        -- 
        Ronald Fischer <ynnor@mm.st>

      If myprog.exe can not be run, system(...) returns on my platform 256 (which is exit code 1, no child-error), and, as you point out, sets $! to some error code.

      You have a broken Perl if that's true.

      If myprog can not be run, system sets $? to -1 and sets the error in $!.

      If a shell command cannot be run, system sets $? to something other than -1 (since the shell was successfully executed) and $! contains no meaningful information. The shell cannot possibly change the parent's errno.

        By that logic, all windows perls are broken, which may or may not be true.
        You have a broken Perl if that's true.

        Well, it's pretty easy to reproduce, and the effect is the same in ActiveState 5.8.8 und 5.10. If I find the time, I'll try it with Strawberry...

        The shell cannot possibly change the parent's errno.
        Certainly not. It would need to communicate the information in a different way to the parent process. Well, this is a theoretical question, because Perl - likely in order to be portable - is not programmed that way, but: If it would be possible on Windows to somehow get the full (i.e. 32 Bit) Exitcode, we could use this information: If the shell can't execute a program, it sets this exitcode to 9009.

        OTOH, this would still make it indistinguishable from a program which deliberately sets that exit code..

        -- 
        Ronald Fischer <ynnor@mm.st>