What happens to daemon threads when the main thread exits? How are they shut down? Is there a way the ensure that cleanup code is executed?
Here's a sketch of the situation I have:
import os
import subprocess
import threading
import glob
import datetime
def do_big_job(result='result.txt'):
tmpfile = result+'.tmp'
err = subprocess.call(['my_time_consuming_script', '-o', tmpfile])
if err == 0:
os.rename(tmpfile, result)
else:
os.remove(tmpfile) # process failed, clean up temp file
def main():
not_done = True
update = 0
while not_done:
# we can see if new data are available,
# and start a process to get/prep it
if new_data_available():
args = ('result{0:05}.txt'.format(update),)
th = threading.Thread(target=do_big_job, args=args)
update = update + 1
th.daemon = True
th.start()
# but we don't need/want to wait for that process
# to complete before continuing to iterate
currently_available = glob.glob('result*.txt')
# <snip>
# rest of loop just uses what is available,
# we don't want/need to block for updated data
# to meet other responsiveness requirements
I'd like to make sure that I don't leave any temporary files (or zombie processes) lying around if the main thread dies while one (or more) of the do_big_job
threads are still running, but I also can't just set daemon=False
since I cannot wait for them to complete when main exits.
To actively end a (daemon) thread the most common method is to signal the thread the request to have it terminated, the thread should check for this request in regular intervals and end itself once such a request has been made. Voting is disabled while the site is in read-only mode.
The threads which are always going to run in the background that provides supports to main or non-daemon threads, those background executing threads are considered as Daemon Threads. The Daemon Thread does not block the main thread from exiting and continues to run in the background.
This process of stopping the daemon thread can be automated using the atexit module. The atexit module allows a function to be registered that will be called by the Python interpreter right before the process is exited.
We can close a thread by returning from the run function at any time. This can be achieved by using the “return” statement in our target task function. If the threading. Thread class has been extended and the run() function overridden, then the “return” statement can be used in the run() function directly.
When main thread exits all daemon threads exit too. So if your main() exits all daemon threads will exit too.
However, and coming to the second part of your question,according to the official python threading docs for I/O operations this may not happen gracefully.
Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly. If you want your threads to stop gracefully, make them non-daemonic and use a suitable signalling mechanism such as an Event.
So if you want to check whether there are any zombie threads lying around, you can call the isAlive() function. Now as to how to ensure that cleanup code is executed after the main thread dies; I think it depends on what you mean by dies.
If you mean normal exit of the script (e.g. KeyboardInterrupt exception, sys.exit() is called) then it's really worth taking a look at the atexit module, which registers functions to be executed upon the termination of a process.
If by "dying" you mean that main() is killed by a signal, or a Python fatal internal error occurs, or os._exit() is called then atexit module won't work. In that case, a possible solution that comes to my mind would be to create another watchdog process that is constantly monitoring your main() and will run the cleanup code when appropriate.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With