C
Carl Banks
Ok, so I have an issue with cleaning up threads upon a unexpected exit. I came up with a solution but I wanted to ask if anyone has any advice or warnings.
Basically I am writing a Python library to run certain tasks. All of the calls in the library start worker threads to do the actual work, and some ofthe worker threads are persistent, others not. Most threads have cleanup work to do (such as deleting temporary directories and killing spawned processes).
For better or worse, one of the requirements is that the library can't cause the program to hang no matter what, even if it means you have to forego cleanup in the event of an unexpected exit. Therefore all worker threads run as daemons. Nevertheless, I feel like the worker threads should at leastbe given a fair opportunity to clean up; all threads can be communicated with and asked to exit.
One obvious solution is to ask users to put all library calls inside a with-statement that cleans up on exit, but I don't like it for various reasons.
Using atexit doesn't work because it's called after the daemon threads are killed.
Here's the solution I came up with: in the library's init function, it willstart a non-daemon thread that simply joins the main thread, and then asksall existing worker threads to exit gracefully before timing out and leaving them to be killed. So if an exception ends the main thread, there is still a chance to clean up properly.
Does anyone see a potential problem with this approach? It it possible that this will cause the program to hang in any case? We can assume that all calls to the library will occur from the main thread, or at least from the same thread. (If that isn't the case, then the caller has taken responsibility to ensure the program doesn't hang.)
This is Python 2.7, and it's only ever going to run on Windows.
Thanks for any advice/warnings.
Carl Banks
Basically I am writing a Python library to run certain tasks. All of the calls in the library start worker threads to do the actual work, and some ofthe worker threads are persistent, others not. Most threads have cleanup work to do (such as deleting temporary directories and killing spawned processes).
For better or worse, one of the requirements is that the library can't cause the program to hang no matter what, even if it means you have to forego cleanup in the event of an unexpected exit. Therefore all worker threads run as daemons. Nevertheless, I feel like the worker threads should at leastbe given a fair opportunity to clean up; all threads can be communicated with and asked to exit.
One obvious solution is to ask users to put all library calls inside a with-statement that cleans up on exit, but I don't like it for various reasons.
Using atexit doesn't work because it's called after the daemon threads are killed.
Here's the solution I came up with: in the library's init function, it willstart a non-daemon thread that simply joins the main thread, and then asksall existing worker threads to exit gracefully before timing out and leaving them to be killed. So if an exception ends the main thread, there is still a chance to clean up properly.
Does anyone see a potential problem with this approach? It it possible that this will cause the program to hang in any case? We can assume that all calls to the library will occur from the main thread, or at least from the same thread. (If that isn't the case, then the caller has taken responsibility to ensure the program doesn't hang.)
This is Python 2.7, and it's only ever going to run on Windows.
Thanks for any advice/warnings.
Carl Banks