John Doe
John Doe

Reputation: 1138

system() returns bad exit code

I am using system to call an external application and I need to interpret its exit code.

I know that system returns the exit code from the command multiplied by 256, but when in foo.bat I write exit 256 the result is zero.

Why is this happening?

Upvotes: 2

Views: 1588

Answers (3)

ikegami
ikegami

Reputation: 385506

Windows uses 32-bit exit codes, so exit 256 is perfectly valid.

>cmd /c exit 256

>echo %ERRORLEVEL%
256

However, Perl only keeps the least significant 8 bits.

>perl -e"system 'exit 256'; CORE::say $?>>8"
0

>perl -e"system 'exit 266'; CORE::say $?>>8"
10

This is a Perl defect for which there's no good reason. If you use Win32::Process instead of system, you can obtain the correct exit code.

>perl -MWin32::Process=NORMAL_PRIORITY_CLASS,INFINITE -e"Win32::Process::Create(my $proc, $ENV{COMSPEC}, 'cmd /c exit 256', 0, NORMAL_PRIORITY_CLASS, '.') or die $^E; $proc->Wait(INFINITE); $proc->GetExitCode(my $exit_code); CORE::say $exit_code;"
256

Upvotes: 5

durgesh
durgesh

Reputation: 21

All the possibilities of failure can be obtained by examining $?.

$exit_val    = $? >> 8;
$signal      = $? & 127;
$dumped_core = $? & 128;`

To quote from perldoc perlvar :

  • $CHILD_ERROR

  • $?

    The status returned by the last pipe close, backtick (``) command, successful call to wait() or waitpid(), or from the system() operator. This is just the 16-bit status word returned by the traditional Unix wait() system call (or else is made up to look like it). Thus, the exit value of the subprocess is really ($? >> 8 ), and $? & 127 gives which signal, if any, the process died from, and $? & 128 reports whether there was a core dump.

Upvotes: -1

Borodin
Borodin

Reputation: 126722

The return code is a single-byte value from zero to 255.

The most reliable way to check the status of a system call is to examine $?. It's documented in perldoc perlfunc like this

if ($? == -1) {
    print "failed to execute: $!\n";
}
elsif ($? & 127) {
    printf "child died with signal %d, %s coredump\n",
        ($? & 127),  ($? & 128) ? 'with' : 'without';
}
else {
    printf "child exited with value %d\n", $? >> 8;
}

Upvotes: 2

Related Questions