Python- executing code lines after host force closing [duplicate] - python

I have a python 3 script and it runs on boot. And it work with some resources I want it free on exit.
How can I manage that script is going to exit if I'm killing it with kill -6 $PID.
Or any other ideas about how to send exit command and detect it in script.

The signal module is what you are looking for.
import signal
def handler(signum, frame):
print('Signal handler called with signal', signum)
signal.signal(signal.SIGABRT, handler)
Within the handler function you could terminate with sys.exit().
However, it is more common to use SIGINT (that's what happens when you press CTRL+C in the terminal) or SIGTERM to terminate a program. If you don't have cleanup code you don't need to write a single line of code to handle SIGINT - by default it raises a KeyboardInterrupt exception which, if not caught (that's a reason why you should never use blank except: statements), causes your program to terminate.

Related

How exactly is SIGILL generated?

I have a program using tensorflow on a non-supported hardware, so everytime i run it, i get the "Illegal instruction (Core dumped)" error
my main goal is to capture this error. i don't want to solve it.
The error is not printed to the stderr of my program, it's printed to the stderr of bash.
then my program exists with code 33792 which is 132 (SIGILL)
And i cannot capture it using the method mentioned here, because i'm running my command using docker run and i can't pass it the curly brackets
Is there any way to capture the stdout of bash without the curly brackets?
Also how exactly is SIGILL generated? what exactly is happening behind the scenes?
Is SIGILL triggered in the parent process (bash in my case) and passed to the child process (my program)? or vice versa?
i tried adding a SIGILL handler in my program to see if i can capture it, but my program froze instead of printing the "illegal instruction" error.
I'm using Debian 11 and my program is written in python.
Edit:
The SIGILL kills my python program and my goal is to capture the SIGILL from inside my program, print some error and kill my program afterward.
I don't want the (Illegal instruction) error printed to be printed in the bash's stderr, I want it to be printed to my program's stderr or stdout.
Edit: here's the sigill handler I have in my code
def sigill_handler(sig, frame):
print("Illegal Instruction. terminating.")
signal.signal(signal.SIGILL, sigill_handler)
notice that this is the only signal I'm handling in my code
Citing https://docs.python.org/3/library/signal.html:
Execution of Python signal handlers
A Python signal handler does not get executed inside the low-level (C) signal handler. Instead, the low-level signal handler sets a flag which tells the virtual machine to execute the corresponding Python signal handler at a later point(for example at the next bytecode instruction). This has consequences:
It makes little sense to catch synchronous errors like SIGFPE or SIGSEGV that are caused by an invalid operation in C code. Python will return from the signal handler to the C code, which is likely to raise the same signal again, causing Python to apparently hang. From Python 3.3 onwards, you can use the faulthandler module to report on synchronous errors.
A long-running calculation implemented purely in C (such as regular expression matching on a large body of text) may run uninterrupted for an arbitrary amount of time, regardless of any signals received. The Python signal handlers will be called when the calculation finishes.
If the handler raises an exception, it will be raised “out of thin air” in the main thread. See the note below for a discussion.
According to https://docs.python.org/3/library/faulthandler.html, all the faulthandler can do is to dump a stack trace, so it does not help for your requirement.
What you could do is to run your possibly failing program from your own wrapper program where you can check the wait status and decide what you display to the user if the program was killed by SIGILL.
It would be better to check if your program runs on a supported platform before using any tensorflow functions.

Keyboard interrupt bash and python script running in parallel

I have to execute two operations at the same time, one through a bash script and another through a python script. The simplest way to do it that I've found so far is to create a parent bash script to execute the two in parallel, such as this:
#!/bin/bash
bash process1.sh &
python3 process2.py &
I want to be able to interrupt the two processes at the same time using keyboard interrupt Ctrl+C. I tried adding
trap 'kill %1; kill %2' SIGINT
but the python script does not close as I'd like. In the python script there is a loop that should stop after the keyboard interrupt and perform some more operations after that, something like this
try:
# do something
except KeyboardInterrupt:
# Keyboard interrupt (Ctrl + C) detected
pass
# then do some final operations
but using kill does not propagate the keyboard interrupt to the python script, it just terminates the program as it is.
Is there a way to not kill the child python script, but to propagate the SIGINT to it?
Try this:
trap 'kill -INT %1 %2' INT
kill %2 sends SIGTERM (the default signal) to the Python process, not SIGINT. You want kill -INT inside the trap code.

Python: "Unbreakable" infinite loop was exited

I'm recording data with a RuuviTag Bluetooth sensor which sends temperature values to my RaspberryPi.
According to the RuuviTag Python library docu I'm supposed to use the function RuuviTagSensor.get_datas(handle_data) which starts an infinite loop of the function handle_data().
In my case, I designed it like:
def handle_data(found_data):
temperature_measurement = found_data[1]['temperature']
publish_via_mqtt(temperature_measurement)
and I wrapped it all up in:
while True:
try:
RuuviTagSensor.get_datas(handle_data)
except Exception:
logger.exception(f"An error occurred at {datetime.now(timezone.utc)}")
reconnect_mqtt()
However, overnight, I broke ...
The logs say:
INFO:ruuvitag_sensor.ble_communication:Problem with hciconfig reset. Retry reset.
INFO:ruuvitag_sensor.ble_communication:Problem with hciconfig reset. Retry reset.
INFO:ruuvitag_sensor.ble_communication:Problem with hciconfig reset. Retry reset.
INFO:ruuvitag_sensor.ble_communication:Problem with hciconfig reset. Exit.
So it seems like the RaspberryPi hat a Bluetooth problem and tried to reconnect with the Ruuvis ... and when that did not work 3 times, he just EXITED PYTHON? Am I correct? Is there a way to restart the whole script if it is exited or handle this exit?
In the library code, exit(1) is called if the sensor cannot be started after three attempts.
Calling exit raises the SystemExit exception. SystemExit does not inherit from Exception, and so is not caught by the try/except block in the code in the question. This behaviour seems to be intentional, according to the project's README:
In case of errors, application tries to exit immediately, so it can be automatically restarted.
Trapping SystemExit within the program is possible (except SystemExit:) if you want to force the library to keep retrying.

Python VS Code Debug - Capture SIGTERM?

I'd like to force sys.exit() when the python debugger is stopped. When I stop the debugger I see Terminated: 15 so I assume this is SIGTERM. However, when stopping the debugger, my kill function isn't called.
def kill(sig, frame):
sys.exit(0)
signal.signal(signal.SIGINT, kill)
signal.signal(signal.SIGTERM, kill)
When stopping the vscode debugger, what signal is sent?
Edit:
Just tried all of them. No love
for s in signal.Signals:
try:
signal.signal(s, self._kill)
except:
pass
For now we seem to be OOL (out of luck) - I ran into the same issue and found that VS Code python extension does issue a SIGKILL on debug stop, which cannot be cought.
Unlike the node.js extenstion, the Python extension also does not support setting the type to SIGTERM or SIGINT.
The only workaround I found is to have an open terminal (type: Pythen Debug Terminal) in VS Code. It should show the python command behavior and output during debug. Bring the terminal into focus by clicking on it and press ctrl-C manually. This should stop the debugged program gracefully and your catching the SIGTERM or SIGINT will work.

Python detect kill request

I have a python 3 script and it runs on boot. And it work with some resources I want it free on exit.
How can I manage that script is going to exit if I'm killing it with kill -6 $PID.
Or any other ideas about how to send exit command and detect it in script.
The signal module is what you are looking for.
import signal
def handler(signum, frame):
print('Signal handler called with signal', signum)
signal.signal(signal.SIGABRT, handler)
Within the handler function you could terminate with sys.exit().
However, it is more common to use SIGINT (that's what happens when you press CTRL+C in the terminal) or SIGTERM to terminate a program. If you don't have cleanup code you don't need to write a single line of code to handle SIGINT - by default it raises a KeyboardInterrupt exception which, if not caught (that's a reason why you should never use blank except: statements), causes your program to terminate.

Categories