3

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.

zdim
  • 64,580
  • 5
  • 52
  • 81
  • Okay, I got the ans,My mistake is I am returning to the subroutine in Code 2. I should be returning to exitcode of Code 2 to code 1. It is done like, my $tocode1 = subroutine(@flag_value); sub subroutine{ my (@P)= @_; #do req ops and assigns $exitcode exit ($exitcode); return $exitcode; } return $tocode1; – perlenthusiast Dec 12 '22 at 07:07
  • Sure, Thank you zdim, I am sure, the ans you provide is a better way. – perlenthusiast Dec 12 '22 at 07:11
  • 1
    "_the ans you provide is a better way_" -- well, I didn't mean to say that :) Please let me know of what is unclear or missing etc, in what I posted – zdim Dec 12 '22 at 07:54
  • 1
    you are using backticks, which gets output of the command. See: https://perldoc.perl.org/functions/system – Alexandr Evstigneev Dec 12 '22 at 10:31
  • Thanks a lot @zdim . That worked and the explanation was very clear. I was able to understand and implement the logic. – perlenthusiast Dec 27 '22 at 19:47
  • Thanks for pointing the backticks @AlexandrEvstigneev . I realized that. Now have edited the code according to suggestions. That was very much helpful :D – perlenthusiast Dec 27 '22 at 19:49

1 Answers1

4

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" docs 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);
zdim
  • 64,580
  • 5
  • 52
  • 81
  • Nice answer. Since you listed some other modules to call external programs: [IPC::Cmd](https://metacpan.org/pod/IPC::Cmd) is a core module that maybe could be mentioned – Håkon Hægland Dec 12 '22 at 09:43
  • @HåkonHægland An interesting library, thank you (I had never looked into it before). Added – zdim Dec 14 '22 at 08:52