Abruptly kill a python thread which indirectly calls methods containing locks - python

I have a thread (say thread_a) which execute a method (say method_a()). This method_a is calling method (say method_b) which uses a lock.I want to terminate this thread abruptly. How can I do this without damaging the consistency of the lock. Give bellow is a structure of my code,
def method_a()
#codes
method_b()
#codes
def method_b()
lock.acquire()
#codes
lock.release()
thread_a = threading.Thread(target=method_a)
thread_a.start()
What is the best way to terminate this thread_a. I want to keep the correct state of the lock even if the thread is killed abruptly. Any ideas?

Related

Python 3 - How to terminate a thread instantly?

In my code (a complex GUI application with Tkinter) I have a thread defined in a custom object (a progress bar). It runs a function with a while cicle like this:
def Start(self):
while self.is_active==True:
do it..
time.sleep(1)
do it..
time.sleep(1)
def Stop(self):
self.is_active=False
It can terminate only when another piece of code, placed in another thread, changes the attribute self.is_active using the method self.Stop(). I have the same situation in another custom object (a counter) and both of them have to work together when the another thread (the main one) works.
The code works, but I realized that the two threads associated with the progress bar and the counter don't terminate instantly as I wanted, because before to temrinate, they need to wait the end of their functions, and these ones are slow becose of the time.sleep(1) instructions. From the user point of view, it means see the end of the main thread with the progress bar and the cunter that terminate LATE and I don't like it.
To be honest I don't know how to solve this issue. Is there a way to force a thread to terminate instantly without waiting the end of the function?
First off, to be clear, hard-killing a thread is a terrible idea in any language, and Python doesn't support it; if nothing else, the risk of that thread holding a lock which is never unlocked, causing any thread that tries to acquire it to deadlock, is a fatal flaw.
If you don't care about the thread at all, you can create it with the daemon=True argument, and it will die if all non-daemon threads in the process have exited. But if the thread really should die with proper cleanup (e.g. it might have with statements or the like that manage cleanup of resources outside the process, that won't be cleaned up on process termination), that's not a real solution.
That said, you can avoid waiting a second or more by switching from using a plain bool and time.sleep to using an Event and using the .wait method on it. This will allow the "sleeps" to be interrupted immediately, at the small expense of requiring you to reverse your condition (because Event.wait only blocks while it's false/unset, so you need the flag to be based on when you should stop, not when you are currently active):
class Spam:
def __init__(self):
self.should_stop = threading.Event() # Create an unset event on init
def Start(self):
while not self.should_stop.is_set():
# do it..
if self.should_stop.wait(1):
break
# do it..
if self.should_stop.wait(1):
break
def Stop(self):
self.should_stop.set()
On modern Python (3.1 and higher) the wait method returns True if the event was set (on beginning the wait or because it got set while waiting), and False otherwise, so whenever wait returns True, that means you were told to stop and you can immediately break out of the loop. You also get notified almost immediately, instead of waiting up to one second before you can check the flag.
This won't cause the real "do it.." code to exit immediately, but from what you said, it sounds like that part of the code isn't all that long, so waiting for it to complete isn't a big hassle.
If you really want to preserve the is_active attribute for testing whether it's still active, you can define it as a property that reverses the meaning of the Event, e.g.:
#property
def is_active(self):
return not self.should_stop.is_set()
the safest way to do it without risking a segmentation fault, is to return.
def Start(self):
while self.is_active==True:
do it..
if not self.is_active: return
time.sleep(1)
if not self.is_active: return
do it..
if not self.is_active: return
time.sleep(1)
def Stop(self):
self.is_active=False
python threads need to free the associated resources, and while "killing" the thread is possible using some C tricks, you will be risking a segmentation fault or a memory leak.
here is a cleaner way to do it.
class MyError(Exception):
pass
def Start(self):
try:
while self.is_active==True:
do it..
self.check_termination()
time.sleep(1)
self.check_termination()
do it..
self.check_termination()
time.sleep(1)
except MyError:
return
def check_termination(self):
if not self.is_active:
raise MyError
and you can call self.check_termination() from inside any function to terminate this loop, not necessarily from inside Start directly.
Edit: ShadowRanger solution handles the "interruptable wait" better, i am just keeping this for implementing a kill switch for the thread that can be checked from anywhere inside the thread.

What is the best way to terminate a thread in python?

I am implementing a Flask application and I'm calling a function A, based on a request. Inside the function A, there is another function called B and it is called. But, I don't need to wait until the end of the execution of function B to return the output from function A. I have done it with the following code implementation.
from threading import Thread
def functionA():
result = doSomething1()
Thread(target=functionB).start()
return result
def functionB():
# Do something after the execution of doSomething1()
Here, I am starting a new thread and do what I need to do but, I do not terminate the newly started thread. Do I need to terminate that thread by myself? If so, what is the best way to do that?
A thread will terminate on its own. To see if it is alive you can use thread.is_Alive()
If you must force termination of a thread, use thread.join() would be the closes option, as this blocks the calling thread until the thread in question has finished.
Also refer to the docs for more info on the Threading functions
https://docs.python.org/3/library/threading.html

Guarding critical section in a multithreaded program

I have a multithreaded Python program (financial trading) in which certain threads execute critical sections (like in the middle of executing a trade). The thread executing the critical sections are daemon threads. The main thread of the program captures SIGINT and tries to exit the program gracefully by releasing all resources held by child threads. In order to prevent the main thread causing the child threads to terminate abruptly; the main the thread will loop through the list of child thread objects and call their shutdown() function. This function will block till a critical section of the thread completes before returning.
The following is a basic implementation
class ChildDaemonThread(Thread):
def __init__(self):
self._critical_section = False
# other initialisations
def shutdown(self):
# called by parent thread before calling sys.exit(0)
while True:
if not self._critical_section:
break
# add code to prevent entering critical section
# do resource deallocation
def do_critical_stuff(self):
self._critical_section = True
# do critical stuff
self._critical_section = False
def run(self):
while True:
self._do_critical_stuff()
I am not sure if my implementation will work because while the ChildDaemonThread is executing critical section through do_critical_stuff(), if the parent thread calls the child's shutdown(), which blocks till a critical section executes, then at this point two methods of the ChildDaemonThread run() and do_critical_stuff() are called at the same time (I am not sure if this is even legal). Is this possible? Is my implementation correct? Is there a better way to achieve this?
There are some race conditions in this implementation.
You have no guarantee that the main thread will check the value of _critical_section at the right time to see a False value. The worker thread may leave and re-enter the critical section before the main thread gets around to checking the value again. This may not cause any issues of correctness but it could cause your program to take longer to shut down (since when the main thread "misses" a safe time to shut down it will have to wait for another critical section to complete).
Additionally, the worker thread may re-enter the critical after the main thread has noticed that _critical_section is False but before the main thread manages to cause the process to exit. This could pose real correctness issues since it effectively breaks your attempt to make sure the critical section completes.
Of course, the program may also crash due to some other issue. Therefore, it may be better if you implement the ability to recover from an interrupted critical section.
However, if you want to improve this strategy to the greatest extent possible, I would suggest something more like this:
class ChildDaemonThread(Thread):
def __init__(self):
self._keep_running = True
# other initialisations
def shutdown(self):
# called by parent thread before calling sys.exit(0)
self._keep_running = False
def do_critical_stuff(self):
# do critical stuff
def run(self):
while self._keep_running:
self._do_critical_stuff()
# do resource deallocation
workers = [ChildDaemonThread(), ...]
# Install your SIGINT handler which calls shutdown on all of workers
# ...
# Start all the workers
for w in workers:
w.start()
# Wait for the run method of all the workers to return
for w in workers:
w.join()
The key here is that join will block until the thread has finished. This ensures you're not interrupting one mid-critical-section.

Python : printing in multiple threads

I have an implementation of a network system based on Twisted. I noticed that when I run a function (which do some mathematical operations and prints the result) in a new thread, not in the main one, the print function causes Segmentation fault. Is it possible? Is there an option to avoid that?
My approach, based on Bram Cohen's suggestion:
Define a global Lock variable
from threading import Lock
s_print_lock = Lock()
Define a function to call print with the Lock
def s_print(*a, **b):
"""Thread safe print function"""
with s_print_lock:
print(*a, **b)
Use s_print instead of print in your threads.
You need to use a thread lock when you print something in a thread.
Example:
lock = Lock()
lock.acquire() # will block if lock is already held
print("something")
lock.release()
In this way the resource(in this case print) will not be used in the same time by multiple threads.
Using a thread lock is something like focusing the attention on the thread where the lock is acquired.

How does python Rlock work and what is the owner of Rlock?

I am currently practicing python multi-thread module, and I write some code as below, but it is not working as I just expect.
import threading
import thread
import random
import time
lock = threading.RLock()
def func(lock):
print("In Thread " + threading.currentThread().getName())
lock.acquire()
time.sleep(random.random()*10)
lock.release()
print("Out Thread " + threading.currentThread().getName())
def start():
lock.acquire()
for i in range(5):
thread.start_new(func, (lock,))
lock.release()
# for i in range(5):
# thread.start_new(func, (lock,))
start()
print("test")
time.sleep(1)
lock.acquire()
print("main ends")
lock.release()
In my opinion, whether there is time.sleep(1) in the main thread does not count much for the new threads's running, because the lock is global and belongs to the main thread, the lock.acquire() operation would always work fine, so the main thread should not wait for those new threads to proceed. According to the property of thread.start_new(), when the main thread ends, all new threads would also stop. However, when I comment out the time.sleep() line, the program goes as what I have expected, but when I add this line in, the main thread always waits for new threads to finish.
This confuses me a lot and hope someone would explain to me the functionality of Rlock() as well as which thread does it belong to when I create it in the main thread while passing it to the sub-new thread and calling lock.acquire()?
A lock belongs to the thread that last did .acquire() it successfully, until it has been .release()d.
A RLock, short for re-entrant lock is a lock that can be acquired many times by the same thread that acquired it initially; the lock stays locked and held by the thread until each acquisition has been released.
The re-entrancy means here that the execution enters a section of code guarded by the lock, while the lock is held already. Your code does not demonstrate a case where a re-entrant lock is needed but suppose you have functions:
def guarded_op():
with lock:
print("Now doing 1 op")
another_op()
def another_op():
with lock:
print("Now did the another op")
A non-re-entrant lock would not work there, as the "lock was already locked" in guarded op; the locking would fail in another_op; but RLock works just fine.
By the way, you should always use the with statement with locks whenever possible to ensure their orderly release.

Categories

Resources