Handling segmentation fault due to a C++ subprocess spawned by Python code - python-2.7

I have read a few articles about signal handling in Python, and for some reason am not getting the desired output.
This is my C++ code. It is meant to simulate a segmentation fault.
The purpose of the Python code is to run the C++ program as a subprocess and to catch run time errors, if any.
int main()
{
int*a;
a=NULL;
cout<<*a<<endl;
return 0;
}
The python code is as follows:
from subprocess import *
import signal
def handler(signum,frame):
print "Error Occured",signum
raise IOError("Segmentation Fault Occured.")
#The C++ code is already compiled
a = Popen(["./a.out"])
try:
signal.signal(signal.SIGSEGV,handler)
except IOError as e:
print e
When the C++ code is run on the terminal directly, (not using the Python code) this is the output:
Segmentation fault (core dumped)
When the same is run using the Python code, no output is observed.
What is going wrong in my approach?
Thanking you in advance.
PS: I tried this as an alternative and it worked. However, it cannot be used for my application since I cannot use wait() method.
a.wait()
if a.returncode == -11:
print "Segmentation fault, core dumped"

Okay the issue was solved. Instead of using
signal.signal(signal.SIGSEGV,handler)
I used the following:
signal.signal(signal.SIGCHLD,handler)

Related

Why does a child process killed due to a segmentation fault not die immediately?

I need to write a C++ code which accepts a certain input and prints the respective output. This code is meant to be run using the Python subprocess module. Regardless of inputs and outputs, I need to make sure that the Python code does not terminate prematurely due to runtime errors the C++ code encounters. The basic nature of the C++ code is as follows
int main()
{
/*The pointer is initialized to NULL to simulate a segmentation fault
Also the n is meant for simulating input.*/
int *p=NULL,n;
cin>>n;
cout<<*p<<endl; //This causes a segmentation fault.
}
The Python code which runs it, is as follows:
from subprocess import *
from signal import *
def handler(signum,frame):
raise RuntimeError("Runtime Error")
call(["g++","try.cpp"])
a = Popen(["stdbuf","-i0","-o0","-e0","./a.out"],stdin = PIPE,stdout = PIPE)
try:
#Handler for signal due to termination of child process
signal(SIGCHLD,handler)
a.stdin.write("1\n")
temp = a.stdout.readline()
except RuntimeError as e:
print e
print a.returncode
#Returncode of process killed due to SIGSEGV is -11
if a.returncode == -11:
print "Segmentation Fault Occurred"
This is the issue. Even though the C++ code experiences a segmentation fault, the signal handler is invoked, the RuntimeError is raised, but the returncode of the Popen object is none, indicating that the process still lives.
Now if the following change is made to the except block:
a.wait()
print a.returncode
if a.returncode == -11:
print "Segmentation Fault Occurred"
The issue is resolved. The output shows that the returncode of the Popen object is -11 and "Segmentation Fault Occurred" is printed to the screen.
The exact same happens if I try to simulate a floating point exception due to divide-by-zero.
Why does this happen?
From the documentation
Popen.wait()
Wait for child process to terminate. Set and return returncode attribute.
So returncode is not set until wait is called.
Alternately you could perform a non-blocking check to see if process is terminated using poll, which would set returncode as well if terminated.
Popen.poll()
Check if child process has terminated. Set and return returncode attribute.
note that you don't really need the signal call (not sure if it's portable on Windows). The code could be simplified like this:
a = Popen(["stdbuf","-i0","-o0","-e0","./a.out"],stdin = PIPE,stdout = PIPE)
a.stdin.write("1\n")
a.stdin.flush()
temp = a.stdout.readline()
if temp:
# do something
print("output "+temp)
else:
# empty string: recieved process has ended, probably unexpectedly
# because it should have printed something
pass
returncode = a.wait()
#Returncode of process killed due to SIGSEGV is -11
if returncode == -11:
print("Segmentation Fault Occurred")
note that you have to a.stdin.flush() to be sure the input reaches the c++ program.

How can I prevent infinite loop in subprocess of python?

I am writing a python script that executes another program with bash command.
I am using subprocess.Popen() function for it. However in some conditions the external program gives me an error and tries to run same comment infinitely.
How can I catch that error and break Popen function.
Assume that program gives its error as an output.
You can use poll() or communicate() function for this. These methods return returncode once the process terminates. The return code is None as long as programme is running.
You can try using below code
from subprocess import Popen
process = Popen('bash your_script.sh')
while process.poll() is None:
print 'keep running'
process.terminate()

How to quit python script in gdb-python?

I am writing a python(v2.7) script in GDB(v7.5.1-0.7.29). I want to quit the python script when certain condition got false. But i do not want to quit GDB. I tried using sys.exit(), exit() and quit(), but in those case they also quit GDB. Is there any way to just quit the python script but not the gdb. Like ctrl + c command but i want this happend only when a certain condition got false.
CTRL+D does that
(gdb) pi
>>> [Press CTRL+D]
(gdb)
You have to raise an exception. Question is what exception to raise; whether you provide code to catch it and whether you want traceback to be printed or not.
If you don't mind traceback to be printed you can raise KeyboardInterrupt. But I presume you want graceful exit without traceback.
If you are writing code for class that integrates into GDB command then you can raise gdb.GdbError. It will be consumed by the code implementing command class and no traceback is printed.
If you are writing a script that is executed by sourcing it then you have to embed your whole script into try / except and catch exception you are raising. In fact, calling exit() also simply raises exception SystemExit, so you may write your script as:
try:
some code
if some_condition:
exit()
some more code
except SystemExit:
pass

segmentation fault while running cython on python3-- gdb output

I have been trying to trace the source of a segfault in a cython program that I inherited. I have implemented gdb under python3 by executing gdb python3 then run my_file.py and got this:
Program received signal SIGSEGV, Segmentation fault.
__pyx_f_7sklearn_5utils_25graph_shortest_path_leftmost_sibling (__pyx_v_node=<optimised out>)
at /home/my_name/.pyxbld/temp.linux-x86_64-3.4/pyrex/sklearn/utils/graph_shortest_path_strat.c:3195
3195 __pyx_t_1 = (__pyx_v_temp->left_sibling != 0);
Thanks #Veedrac
The call appears as follows:
landmark_points=[random.randint(0,kng.shape[0]) for r in range(self.number_landmark_points)]
self.dist_matrix_=graph_shortest_path_strat(kng,landmark_points,method=self.path_method,directed=F‌​alse).
Basically instead of calculating the distances between every single point in a graph I want to calculate the distance between all points and a limited number of points defined in an array. where landmark_points is an array of integers kng is a graph of nearest neighbors
kng = kneighbors_graph(self.nbrs_, self.n_neighbors,mode='distance')
the graph_shortest_path is a .pyx code. And I am using version is 0.15.1
#Veedrac thanks for your help. I actually traced the error to the fact that I was using random.randint, when I should have been generating unique random integers with random.sample.

SIGSEGV; missing file; when running program using sscanf

I will below describe the error that I get when calling the function sscanf.
Some of my code:
#include <cstdio>
(..)
int device_num = 0;
int frameTime = sscanf(currentStringVector[2].c_str(), "%d", &device_num);
It is part of a module of OmNet++, so I compile it using OmNet++ .
I get the following error message in GDB:
"Program received signal SIGSEGV, Segmentation fault.
__rawmemchr_sse2 () at ../sysdeps/x86_64/multiarch/../rawmemchr.S:31
31 ../sysdeps/x86_64/multiarch/../rawmemchr.S: Filen eller katalogen finns inte.
in ../sysdeps/x86_64/multiarch/../rawmemchr.S"
The problem started to incur when I called sscanf.
I am running the program in Ubuntu on a 64-bits system.
How do I resolve the above problem?
Thanks!
With OMNeT++, you can use a debugger like gdb when running your program from the command line. The IDE also lets you debug your code.
My guess is that currentStringVector[2].c_str() is not valid. Maybe the vector is smaller than that.