Home > Software engineering >  Can't stop running thread
Can't stop running thread

Time:07-19

I've a python program executing 3 different threads.

t1 = Thread(target=calculate_statistics, args=(ip_slave_1, path_script_slave_1, logger))
t1.daemon = True
t1.start() 
t2 = Thread(target=calculate_statistics, args=(ip_slave_2, path_script_slave_2, logger))
t2.daemon = True
t2.start() 
t3 = Thread(target=computing, args=("1"))
t3.daemon = True
t3.start() 
t1.join()
t2.join()
t3.join()

Thread are executing well. The problem is that to stop the whole program, I have to digit many times CTRL C. I see this message on the screen: (FIRST CTRL C):

^CTraceback (most recent call last):
  File "/mnt/roaming.py", line 116, in <module>
    t1.join()
  File "/usr/lib/python3.9/threading.py", line 1060, in join
  File "/usr/lib/python3.9/threading.py", line 1080, in _wait_for_tstate_lock

c (SECOND CTRL C)

^CException ignored in: <module 'threading' from '/usr/lib/python3.9/threading.pyc'>
Traceback (most recent call last):
  File "/usr/lib/python3.9/threading.py", line 1477, in _shutdown
KeyboardInterrupt:

Each thread is executing an infinite loop. How can I kill the threads when I press CTRL C? This are the threads functions:

def calculate_statistics(ip_slave, path_script_slave, logger):
    while True:
      current_time = datetime.datetime.now()
      result = os.popen("perl "   str(path_script_slave)   "SYSTEMCMD.pl uf_rxinfo all").read()
      rssi = result.split(",",1)[1]
      rssi = rssi.split(",",1)[0]
      agc = result.split(",",1)[1]
      agc = agc.split(",",1)[1]
      agc = agc.split(",",1)[0]
      auth = result.split(",",1)[1]
      auth = auth.split(",",1)[1]
      auth = auth.split(",",1)[0]
      print("["   str(current_time)   "]" "[SLAVE]"   "["   str(ip_slave)   "] "  "RSSI: "   str(rssi)   "; AGC: "   str(agc)   "; AUTH: "   str(auth)  ".")
      row = str(current_time)   " -IP "   str(ip_slave)   " -RSSI "   str(rssi)   " -AGC "   str(agc)   " -AUTH "   str(auth)
      logger.info(row)
      time.sleep(0.2)
def computing(f_name):
    time.sleep(1)
    while True:
      a_file = open("slaves.log", "r")
      lines = a_file.readlines()
      last_lines = lines[-8:]
      rssi_slave_1 = []
      rssi_slave_2 = []
      agc_slave_1 = []
      agc_slave_2 = []
      auth_slave_1 = []
      auth_slave_2 = []
      f = open("diff.log", "w")
      for element in last_lines:
        f.write(str(element))
        if(element.split("-IP")[1].split(" ")[1]) == str(ip_slave_1):
          rssi_slave_1.append(element.split("-RSSI")[1].split(" ")[1])
          agc_slave_1.append(element.split("-AGC")[1].split(" ")[1])
          auth_slave_1.append(element.split("-AUTH")[1].split(" ")[1].split("\n")[0])
        else:
          rssi_slave_2.append(element.split("-RSSI")[1].split(" ")[1])
          agc_slave_2.append(element.split("-AGC")[1].split(" ")[1])
          auth_slave_2.append(element.split("-AUTH")[1].split(" ")[1].split("\n")[0])          
      f.close()
      print(rssi_slave_1)
      print(rssi_slave_2)
      print(agc_slave_1)
      print(agc_slave_2)
      print(auth_slave_1)
      print(auth_slave_2)
      algorithm(rssi_slave_1,rssi_slave_2,agc_slave_1,agc_slave_2,auth_slave_1,auth_slave_2)
      time.sleep(1)

CodePudding user response:

The canonical way is to have your main thread wait in an infinite loop, and signal the other threads with a threading.Event and replace any infinite loop within the threads with something that waits for that event to have been set.

stop_event.wait(x) would replace any time.sleep(x) you'd have in the processing loops.

import random
import threading
import time

stop_event = threading.Event()


def ponder(thing):
    while not stop_event.wait(random.uniform(0.9, 1.1)):
        print(f"Thinking about {thing}...")
    print(f"Ah! Stopping thinking about {thing}.")


threads = [
    threading.Thread(target=ponder, args=(arg,))
    for arg in ["spam", "eggs", "toast"]
]

for thread in threads:
    thread.start()

while True:
    try:
        time.sleep(1)
    except KeyboardInterrupt:
        print("Keyboard interrupt caught.")
        stop_event.set()
        break

for thread in threads:
    thread.join()

print("Done!")

The output of this example is e.g.

Thinking about eggs...
Thinking about spam...
Thinking about toast...
Thinking about eggs...
Thinking about spam...
Thinking about toast...
Thinking about toast...
Thinking about eggs...
Thinking about spam...
Thinking about spam...
Thinking about toast...
Thinking about eggs...
^CKeyboard interrupt caught.
Ah! Stopping thinking about spam.
Ah! Stopping thinking about toast.
Ah! Stopping thinking about eggs.
Done!
  • Related