Home > Mobile >  how to return exit code from one program to another program in perl
how to return exit code from one program to another program in perl

Time:12-28

I have perl Code 2, which is called from perl Code1. return value of code 2 determines, if to proceed further with code 1, or exit. How to write this logic.

Code 1:

my $exit = `perl /home/username/code2.pl -f @flag_value`;
if($exit == 1){
    #Do something;
    exit ;
}else{
        #Do somethingelse;
        exit;

Code 2:

subroutine(@flag_value);
sub subroutine{
    my (@P)= @_;
    #do req ops and assigns $exitcode
    exit ($exitcode);
    return $exitcode;
}

I am unable to build the logic on how to return the exit code from code 2 to 1. $exit has nothing if I return the $exitcode value. Please help me know my mistake.

Tried to reference available solutions, couldnot understand my mistake.

CodePudding user response:

What a program wants to communicate to its caller as its exit is generally the number passed to exit. But then that number is packaged into the high (most significant) 8 bits of a 16-bit word by the UNIX wait call, lower bits being a single bit indicating whether there was a core dump, and the number of the signal that terminated it (if any) in the right-hand (least-significant) seven bits. Then that is returned to the caller and in a Perl program that is available in the $? variable.

As docs for $? in perlvar put it

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.

So in the program that is called from another ("Code 2") you'd exit with: exit $exit_value;.

Then the 16-bit status word described above, that the calling program ("Code 1") receives, is in the $? variable. To get the actual exit value intended by the called program we need to extract the higher bits, by shifting to the right, $? >> 8. One way to organize this

my $output = qx( code2.pl ... );

# First investigate $? & 127 and $? & 128, see "system" for an example
my $exit_value = $? >> 8;

if ($exit_value == 1) ...

Here qx is the operator form of backticks used in the question, which I think is far nicer. See system for one way to look into possible errors.

Finally, a good option is to use libraries for calling and managing external programs, which make much of this, and way more, much easier. In the tentative order of simpler to more complex some are IPC::System::Simple, Capture::Tiny, IPC::Cmd (core), IPC::Run.

What is posted here is a bit simplified and perhaps loosely phrased at places; the provided links are all minimal required study, and more will come up as you follow through. Among the many SO pages on this, this page has clear ascii art and explanation(s) for that "16-bit word."


However, normally the $? with the status is set prior to unwinding the call stack, and then END blocks run (if any are defined) and global destructors are called (if needed), which both can alter the exit value.

This goes after an explicit exit is issued as well; the program may not actually exit right away after exit. If you want or need to make sure no END blocks run and no destructors are called then use POSIX::_exit($status)


This "Code 2" is a program, which could build the exit code in a subroutine, as indicated in the question. Then the subroutine would return that so that it can be used by exit

# code2.pl

use warnings;
use strict;

...
    
sub subroutine{
    my (@P)= @_;
    #do req ops and assigns $exitcode
    ...    
    return $exitcode;
}

...

exit subroutine(@flag_value);
  • Related