8

I have seen this in many places in Perl scripts:

system("binary");
$exit_code = ($? >> 8)
exit($exit_code)
  1. Why should I use this? Is there an alternative way?

  2. I am calling some binary in system(binary) which I created in C++, which does some stuff and if it fails it gives assert. When I reboot a Linux machine, the stuff which is going fails, and my binary generates assert as expected. But on the Perl side where I called it, it throws a 134 error code, which after 134 >> 8, becomes 0. Ultimately it is making my failure operation a success (which I don't want).

alex
  • 6,818
  • 9
  • 52
  • 103
Dipak
  • 672
  • 3
  • 9
  • 26

2 Answers2

8

perldoc -f system snippet:

The return value is the exit status of the program as returned by the wait call. To get the actual exit value divide by 256.

You can check all the failure possibilities by inspecting $? like this:

$exit_value  = $? >> 8;
$signal_num  = $? & 127;
$dumped_core = $? & 128;
sotona
  • 1,731
  • 2
  • 24
  • 34
7

The program executed under system may return a specific code when it exits. That is packaged into high bits of a number (exit status) which Perl gets and which is available in $?. This is why you want to test that number, for example (but see below)

system($cmd) == 0  or die "Error: $?";

Or, you can separately check $? after the call. If true (non-zero), that only means that there was something other than a clean exit by the application, or a problem with system itself. When you unpack that you are looking for what the application communicated on its exit. In order to merely see whether there was an error you only look at $?, and you are getting a value. So there is no conflict.

What code that program returned is its business (design decision). Programs ideally exit with codes when they fail (if they can detect and handle the problem), and have documentation explaining what code means what. For an example see this answer, and for another comment this one.

As seen in system, you readily get: exit code $? >> 8, signal number $? & 127, and whether core was dumped $? & 128. With your exit status of 134 the signal number is 6, which man 7 signal lists as SIGABRT. The core should be there as well. So that is what you got from your program, and no explicit exit code. Apparently, the program caused abort and dumped core.

In your case, you know where all this comes from -- assert is a macro which calls abort, whereby SIGABRT is raised (man 3 assert abort). Perl gets back that 6 packaged into 134.


Note that assert prints a message to STDERR, so you may want to run the program via qx (backticks), in which case you can capture that error. See the first link above, or search on SO.

zdim
  • 64,580
  • 5
  • 52
  • 81
  • Yes, I know the solution for fix, i will just remove shifting to solve it, But i need a valid reason when to use shifting with system() and when not to use? – Dipak Mar 15 '16 at 09:48
  • 2
    What you said it does really makes sense i found something, The system() function returns two numeric values folded into one. The first is the Unix signal (e.g INT=2, QUIT=3, KILL=9), if any, that terminated the command. This is stored in the lower eight bits returned. The next higher eight bits contain the exit code for the command you executed. – Dipak Mar 15 '16 at 10:02
  • @Dipal Yes! That's the point. Even as the program just sent back a zero the OS knew that something was wrong (signal) and returned to Perl a non-zero. – zdim Mar 15 '16 at 10:06
  • Yes assert is an termination condition so it came in lower 8 bit and there was no error code so higher 8 bits are 0. Am i right now? – Dipak Mar 15 '16 at 10:08
  • I found it it was core dump that's why 128 bit was set from lower 8 bit and plus 6 for assert so finally it was 128|6 = 134 – Dipak Mar 15 '16 at 10:19
  • 1
    @Dipak Nice. Now, there are other tools in Perl for this. If nothing else, modules that make it easier and cleaner. I haven't used them enough to recommend, but there is a lot of good advice on SO. – zdim Mar 15 '16 at 10:21