Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Child thread keeps running even after main thread crashes

I have just started learning concurrency in Python, so my concepts may be a bit wrong, in that case please do correct me. All of the following happened kind of unknowingly.
This is a simple threading example that I understand -

import time
import threading

class CountDown:
    def __init__(self):
        self._running = True
    def stop(self):
        self._running = False

    def run(self, n):
        while self._running is True and n>0:
            print(f'T-minus {n}')
            n -= 1
            time.sleep(2)

c = CountDown()
t = threading.Thread(target=c.run,args=(10,))
t.start()
time.sleep(5)
c.stop()
print('Before join')
t.join()
print('After join')

Which outputs-

T-minus 10
T-minus 9
T-minus 8
Before join
After join

However if I replace the stop method with terminate which isn't implemented-

c = CountDown()
t = threading.Thread(target=c.run,args=(10,))
t.start()
time.sleep(5)
c.terminate()
c.stop()
print('Before join')
t.join()
print('After join')

Which outputs-

In [14]: runfile('/home/walker/Desktop/PYTHON/concurrency/2.py', wdir='/home/walker/Desktop/PYTHON/concurrency')
T-minus 10
T-minus 9
T-minus 8
Traceback (most recent call last):

  File "<ipython-input-14-3759e536ced7>", line 1, in <module>
    runfile('/home/walker/Desktop/PYTHON/concurrency/2.py', wdir='/home/walker/Desktop/PYTHON/concurrency')

  File "/home/walker/.local/lib/python3.6/site-packages/spyder_kernels/customize/spydercustomize.py", line 668, in runfile
    execfile(filename, namespace)

  File "/home/walker/.local/lib/python3.6/site-packages/spyder_kernels/customize/spydercustomize.py", line 108, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "/home/walker/Desktop/PYTHON/concurrency/2.py", line 28, in <module>
    c.terminate()

AttributeError: 'CountDown' object has no attribute 'terminate'


In [15]: T-minus 7
T-minus 6
T-minus 5
T-minus 4
T-minus 3
T-minus 2
T-minus 1

NOTE:
Because of c.terminate() it is clear that Before join and After join don't get printed. Which led me to believe that the main thread has crashed.
However as you can see it automatically starts printing again from T-minus 7 which is contrary to what I think, that if the main thread crashes then the child threads would too.
Why is this happening?

like image 812
jar Avatar asked Oct 27 '18 13:10

jar


1 Answers

Raised Exception crashes only the thread it is in, not the whole program so the process stays alive but If you mark your worker threads as daemon threads, they will die when all your non-daemon threads (e.g. the main thread) have exited.

So if you want to exit the program when your main thread crashes you can set the daemon flag to True

t = threading.Thread(target=c.run,args=(10,), daemon=True)
like image 61
Mohit Solanki Avatar answered Sep 21 '22 15:09

Mohit Solanki