I'm trying to handle signals of a child process executed with subprocess.Popen(..., preexec_fn=...).
According to the documentation, preexec_fn is run in the child process, so theoretically the following two programs should behave the same, where the first one handles the signal inside the embedded c code, and the second one handles the signal from outside by a python function.
By examining the exit code being 0 or not, however, I found that only handling inside the c code actually works. Does anyone have an idea why signal handling in python doesn't work?
Thanks!
handling from inside, exit with 0:
from tempfile import TemporaryDirectory
import subprocess
import signal
import os
c_code = """
#include <csignal>
#include <cstdlib>
#include <iostream>
int main() {
std::signal(SIGFPE, [](int){std::quick_exit(0);}); // handling the signal here
std::cout <<3/0 <<std::endl;
}
"""
def handle_sigfpe():
# signal.signal(signal.SIGFPE, lambda: os.exit(0)) # not handling here
pass
def main():
print(f'main pid: {os.getpid()}', flush=True)
with TemporaryDirectory() as d:
code_path = f'{d}/a.cpp'
bin_path = f'{d}/a'
with open(code_path, 'w') as f:
print(c_code, file=f)
assert(subprocess.run(['g++', '-o', bin_path, code_path]).returncode == 0)
p = subprocess.Popen([bin_path], preexec_fn=handle_sigfpe)
p.wait()
print(f'return code: {p.returncode}', flush=True)
main()
handling from outside, exit with -8 (SIGFPE):
from tempfile import TemporaryDirectory
import subprocess
import signal
import os
c_code = """
#include <csignal>
#include <cstdlib>
#include <iostream>
int main() {
// std::signal(SIGFPE, [](int){std::quick_exit(0);}); // not handling the signal here
std::cout <<3/0 <<std::endl;
}
"""
def handle_sigfpe():
signal.signal(signal.SIGFPE, lambda: os.exit(0)) # but here
pass
def main():
print(f'main pid: {os.getpid()}', flush=True)
with TemporaryDirectory() as d:
code_path = f'{d}/a.cpp'
bin_path = f'{d}/a'
with open(code_path, 'w') as f:
print(c_code, file=f)
assert(subprocess.run(['g++', '-o', bin_path, code_path]).returncode == 0)
p = subprocess.Popen([bin_path], preexec_fn=handle_sigfpe)
p.wait()
print(f'return code: {p.returncode}', flush=True)
main()