vik
vik

Reputation: 21

Perl - $? shows 0 for a -1 return code on Windows 2008 64bit

Using Strawberry Perl 5.12.3

Running manually:

E:\informatica\tools>infacmd isp ping -sn tt -re 0
[ICMD_10033] Command [ping] failed with error [[INFACMD_10053] Service [tt] Domain [dmt3-9-dom-poc] has failed to ping back.].

E:\informatica\tools>echo %ERRORLEVEL%
-1

When I run the same command through Perl's "system", the $? shows 0. Perl code:

use strict;
use warnings;
my $cmd = system("infacmd isp ping -sn tt -re 0");
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;    
}

Output:

[ICMD_10033] Command [ping] failed with error [[INFACMD_10053] Service [tt] Domain     [dmt3-9-dom-poc] has failed to ping back.].
child exited with value 0

The same on Windows 2003 32bit and ActiveState Perl 5.8.8 shows correct results.

Upvotes: 2

Views: 1512

Answers (4)

ikegami
ikegami

Reputation: 385915

That leaves Win32::Process. If the exit code from this is zero, the exit code is zero.

Upvotes: 0

sergio
sergio

Reputation: 69027

I think you should shift $? (I.e., divide it by 256) before doing the branch...

$res = $? >>8;
if ($res == -1)
....

According to system definition in perlfunc

EDIT: I have just read in perl 5 by examples (chapter: handling errors and signals) that on windows you cannot rely on $? To represent the exit state of pipes and system. this could well your case.

the suggestion is,then, to capture the command output and parse it to find out which is the error code...

 my $output = `mycmd 2>&1`;
 if ($output =~ /.....

Upvotes: 0

ikegami
ikegami

Reputation: 385915

You might have better luck with ${^CHILD_ERROR_NATIVE} than with the emulation of unix's process status structure.

Upvotes: 2

rohanpm
rohanpm

Reputation: 4274

I believe that your manual test is not entirely sufficient, as the "errorlevel" variable can be shadowed or matters can otherwise be confused by usage of the shell, so your "infacmd" may not be exiting with the exit code that you think it is.

Your perl script is invoking this subprocess via the shell. Does the behavior change if you invoke it directly instead? (which is usually good practice...)

i.e. if you change the system line to this:

   my $cmd = system('infacmd', 'isp', 'ping', '-sn', 'tt', '-re', '0');

... is the behavior affected at all?

Upvotes: 1

Related Questions