How does Python's async kill signal handling (signal.signal) work? - python

Python has async kill signal handling:
import signal
import sys
def signal_handler(*_):
print("\nExiting...")
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
From what I understand, when Python receives the signal registered here, it stops doing whatever it was doing, and executes the signal handler. If the signal handler doesn't stop the program, when it returns, Python continues doing whatever it was doing.
Is this some sort of special case? It seems strange that something can just interrupt the main thread, make it jump to a complete different function (the signal handler), and then return to what it was doing when the handler returns. I've been programming in Python for a few years, and I'm not aware of anything else in Python that allows you to register a function that at some point just forces the main thread to temporarily do something else no matter what it was doing, before returning to it. Sure, Python has Async support, but you need to await things there before Python will switch what it is executing. The main thread here is not doing any kind of awaiting before focus is taken away from whatever it was doing.
I'm currently studying Rust. As far as I can tell, Rust has a few options for letting you handle kill signals, including:
Running a background thread that watches for an incoming kill signal (like SIGINT), and sets a boolean for your main thread to check, and act on
Running a background thread that watches for an incoming kill signal, and does something about it
Neither interrupt the main thread, and make it execute the signal handler before returning the main thread to what it was doing. This sounds like a Python-specific way to handle kill signals that is built into the interpreter itself, and only possible in a higher level language like Python, where you can have the interpreter run code in-between each line of user code it runs. Or am I wrong?

Related

Python: throw exception in main thread on Windows shutdown (similar to Ctrl+C)

I have a Python script for automating simple tasks. Its main loop looks like this:
while True:
input = download_task_input()
if input:
output = process_task(input)
upload_task_output(output)
sleep(60)
Some local files are altered during task processing. They are modified when the task is started, and restored back to proper state when the task is done, or if exception is caught. Restoring these files on program exit is very important to me: leaving them in altered state causes some trouble later that I'd like to avoid.
When I want to terminate the script, I hit Ctrl+C. It raises KeyboardInterrupt exception which both stops task processing and triggers files restoration. However, if I hit Ctrl+Break, the program is simply terminated: if a task is being processed at this moment, then local files are left in altered state (which is undesirable).
The question: I'm worried about the situation when Windows OS is shutdown by pressing the Power button. Is it possible to make Python handle it exactly like it handles Ctrl+C? I.e. I'd like to detect OS shutdown in Python script and raise Python exception on the main thread.
I know it is possible to call SetConsoleCtrlHandler function from WinAPI and install own handler for situations like Ctrl+C, Ctrl+Break, Shutdown, etc. However, this handler seems to be executed in additional thread, and raising exception in it does not achieve anything. On the other hand, Python itself supposedly uses the same WinAPI feature to raise KeyboardInterrupt on the main thread on Ctrl+C, so it should be doable.
This is not a serious automation script, so I don't mind if a solution is hacky or not 100% reliable.

python on linux trap end of program event

How can I trap or be notified when a program reach the end, just before exit, so I can do some cleanup.
Capturing try/except errors and using signal from import signal allows me to capture most situations, however this is not enough, for example when using deamonize: the interactive task finish and start a new one in background, no control over the close.
To be more specific, when the 'pid' is released.
The module atexit is not a solution, as stated on the documentation:
The functions registered via this module are not called when the
program is killed by a signal not handled by Python, when a Python
fatal internal error is detected, or when os._exit() is called

Setting up idle thread/signalling thread

I'm using Python with wxPython for writing an app.
The method I'm considering to accomplish this may not be the best - if that's the case, let me know because I'm open to refactoring.
Right now, I have one GUI form. The main program start point instantiates an instance of the GUI form then runs wx.mainLoop(), which causes the app's main initial thread to block for the lifetime of the app.
We of course know that when events happen in the UI, the UI thread runs the code for them.
Now, I have another thread - a worker thread. This thread needs to sit idle, and then when something happens in the UI thread, e.g. a button is clicked, I want the worker thread to stop idling and do something else - run a function, say.
I can't envision this right now but I could see as the app gets more complex also having to signal the worker thread while it's actually busy doing something.
I have two questions about this setup:
How can I make my worker thread idle without using up CPU time? Doing something like while True: pass will suck CPU time, while something like while True: time.sleep(0.1) will not allow instantaneous reaction to events.
What's the best way to signal into the worker thread to do something? I don't want the UI thread to execute something, I want the worker thread to be signaled, by the UI thread, that it should change what it's doing. Ideally, I'd have some way for the worker thread to register a callback with the UI itself, so that when a button is clicked or any other UI Event happens, the worker thread is signalled to change what it's doing.
So, is this the best way to accomplish this? And what's the best way to do it?
Thanks!
First: Do you actually need a background thread to sit around idle in the first place?
On most platforms, starting a new thread is cheap. (Except on Windows and Linux, where it's supercheap.) So, why not just kick off a thread whenever you need it? (It's just as easy to keep around a list of threads as a single thread, right?)
Alternatively, why not just create a ThreadPoolExecutor, and just submit jobs to it, and let the executor worry about when they get run and on which thread. Any time you can just think in terms of "tasks that need to get run without blocking the main thread" instead of "worker threads that need to wait on work", you're making your life easier. Under the covers, there's still one or more worker threads waiting on a queue, or something equivalent, but that part's all been written (and debugged and optimized) for you. All you have to write are the tasks, which are just regular functions.
But, if you want to write explicit background threads, you can, so I'll explain that.
How can I make my worker thread idle without using up CPU time? … What's the best way to signal into the worker thread to do something?
The way to idle a thread until a value is ready is to wait on a synchronization object. On any modern OS, waiting on a synchronization object means the operating system stops giving you any CPU time until the object is ready for you.*
There are a variety of different options you can see in the Threading module docs, but the obvious one to use in most cases like this is a Condition. The way to signal the worker thread is then to notify the Condition.
However, often a Queue is a lot simpler. To wait on a Queue, just call its get method with block=True. To signal another thread to wake up, just put something on the Queue. (Under the covers, a Queue wraps up a list or deque or other collection, a Lock, and a Condition, so you just tell it what you want to do—check for a value, block until there's a value, add a value—instead of dealing with waiting and signaling and protecting the collection.)
See the answer to controlling UI elements in wxPython using threading for how to signal in both directions, from a worker thread to a UI thread and vice-versa.
I'd have some way for the worker thread to register a callback with the UI itself, so that when a button is clicked or any other UI Event happens, the worker thread is signalled to change what it's doing.
You can do it this way if you want. Just pass self.queue.put or def callback(value): self.value = value; self.condition.notify() or whatever as a callback, and the GUI thread doesn't even have to know that the callback is triggering another thread.
In fact, that's a pretty nice design that may make you very happy later, when you decide to move some code back and forth between inline and background-threaded, or move it off to a child process instead of a background thread, or whatever.
I can't envision this right now but I could see as the app gets more complex also having to signal the worker thread while it's actually busy doing something.
But what do you want to happen if it's busy?
If you just want to say "If you're idle, wake up and do this task; otherwise, hold onto it and do it whenever you're ready", that's exactly what a Queue, or an Executor, will do for you automatically.
If you want to say, "If you're idle, wake up, otherwise, don't worry about it", that's what a Condition or Event will do.
If you want to say, "If you're idle, wake up and do this, otherwise, cancel what you're doing and do this instead", that's a bit more complicated. You pretty much need to have the background thread periodically check an "interrupt_me" variable while it's busy (and put a Lock around it), and then you'll set that flag as well as notifying the Condition… although in some cases, you can merge the idle and busy cases into a single Condition or Event (by calling an infinite wait() when idle, and a quick-check wait(timeout=0) when busy).
* In some cases—e.g., a Linux futex or a Windows CriticalSection—it may actually spin off a little bit of CPU time in some cases, because that happens to be a good optimization. But the point is, you're not asking for any CPU time until you're ready to use it.

terminate/restart python script if all children are stopped and prevent other children from spawning

I have a socket server that used threading to open a thread for each client that connects.
I also have two other threads that run constantly that are doing maintenance operations.
Basically there is the main thread plus two children running constantly, plus one child for each client that connects.
I want to be able to terminate or restart safely.
I would like to be able to trigger a termination function somehow that would instruct all child processes to terminate safely and then the parent could exit.
Any ideas?
Please do not suggest to connect as a client and send a command that would trigger that.
Already thought of it.
I am looking for a way to do this by executing something in the console.
The python socket server runs as a system service and would like to implement the termination in the init script.
The best way to do this is setup a signal handler in your main thread. This can be done using the signal module. See: http://docs.python.org/library/signal.html. A good way would be to trap the CTRL-C signal (SIGINT).
Please note that the signal handler can also be a class method, so you do not have to use a global method (it took me a while to discover that).
def __init__(self):
signal.signal(signal.SIGINT, self.just_kill_me)
def just_kill_me(self, sig, frame):
self.stopped = True
for t in self.threads:
t.join()
It is not possible to send the equivalent of a kill signal to a thread. Instead you should set a flag that will signal the children to stop.
Your child threads should run in a loop, periodically checking if the parent requests them to stop.
while not parent.stopped:
do_some_maintenance_work

Interrupting Python raw_input() in a child thread with ^C/KeyboardInterrupt

In a multithreaded Python program, one thread sometimes asks for console input using the built-in raw_input(). I'd like to be able to be able to close the program while at a raw_input prompt by typing ^C at the shell (i.e., with a SIGINT signal). However, when the child thread is executing raw_input, typing ^C does nothing -- the KeyboardInterrupt is not raised until I hit return (leaving raw_input).
For example, in the following program:
import threading
class T(threading.Thread):
def run(self):
x = raw_input()
print x
if __name__ == '__main__':
t = T()
t.start()
t.join()
Typing ^C does nothing until after the input is finished. However, if we just call T().run() (i.e., the single-threaded case: just run raw_input in the main thread), ^C closes the program immediately.
Presumably, this is because SIGINT is sent to the main thread, which is suspended (waiting for the GIL) while the forked thread blocks on the console read. The main thread does not get to execute its signal handler until it grabs the GIL after raw_input returns. (Please correct me if I'm wrong about this -- I'm not an expert on Python's threading implementation.)
Is there a way to read from stdin in a raw_input-like way while allowing the SIGINT to be handled by the main thread and thus bring down the whole process?
[I've observed the behavior above on Mac OS X and a few different Linuxes.]
Edit: I've mischaracterized the underlying problem above. On further investigation, it's the main thread's call to join() that's preventing signal handling: Guido van Rossum himself has explained that the underlying lock acquire in join is uninterruptible. This means that the signal is actually being deferred until the entire thread finishes -- so this really has nothing to do with raw_input at all (just the fact that the background thread is blocking so that the join does not complete).
When join is called with no timeout, it is uninterruptable, but when it is called with a timeout, it is interruptable. Try adding an arbitrary timeout and putting it in a while loop:
while my_thread.isAlive():
my_thread.join(5.0)
There is really no easy way around this, period.
One approach is to reorganize and break up your code in a way that parts of functions which need Ctrl-C interruptibility are executed on the main thread. You use queues to send execution requests and likewise for the result values. You need one input queue for the main thread, and one output queue per non-main thread; and a coordinated main thread exit. Obviously, only one blocking function is executed at any given time this way, which may not be what you want.
Here's a working example of this idea with slightly perverse use of semaphores for the coordinated main thread exit.

Categories

Resources