Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

in perl, how do we detect a segmentation fault in an external command

Tags:

perl

Following is C code that is destined to crash:

#include<stdio.h>
#include<stdlib.h>

int main() {
    char *p = NULL;
    printf("Value at P: %c\n", *p);
    return 0;
}

When I compile and run it (RH4 machine with gcc 4.5.2), it predictably gives a segmentation fault:

%  ./a.out
Segmentation fault

%  echo $status
139

If I run it with Perl v5.8.5, this happens:

%  perl -e 'system("./a.out") and die "Status: $?"'
Status: 11 at -e line 1.

The perlvar documentation for $? says that

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.

11 >> 8 is 0, and 11 & 127 is 11.

Why the different exit statuses? If we cannot depend on the exit status, what should be the way to detect segmentation fault in an external command?

like image 708
Unos Avatar asked Aug 20 '13 10:08

Unos


People also ask

What is segmentation fault in terminal?

A segmentation fault (aka segfault) is a common condition that causes programs to crash; they are often associated with a file named core . Segfaults are caused by a program trying to read or write an illegal memory location.

How do you handle a segmentation fault?

It can be resolved by having a base condition to return from the recursive function. A pointer must point to valid memory before accessing it.


2 Answers

Reading the documentation for system might answer your question:

system('a.out');

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:

child died with signal 11, without coredump

The shell just encodes the signal in the status in a different way: 139 - 128 = 11. For example, man bash says:

The return value of a simple command is its exit status, or 128+n if the command is terminated by signal n.

like image 188
choroba Avatar answered Oct 02 '22 18:10

choroba


The OS always sees the same thing... what is returned by the wait(2) family of functions. system(3), et. all, call wait(2). How it peculates up you is what is causing the differences. The shell and the programs do different things and report different ways. Having to shift right 8 to get the most common exit status would be very annoying in shell programs and confuse less tech savvy users.

While the very first UNIX systems I used (genuine Unix) had the same returns I have always wondered if pre-release versions were different and returning the signal and core/dump were a later addition.

My preferred reporting of exit status tends to have the computer split my bits for me.

   my $x = $?;   #save status
   print( "Exit status: %d.%d%s\n",
              $x>>8, $x&127, ($x&128)?"*":"" );
like image 43
Gilbert Avatar answered Oct 02 '22 18:10

Gilbert