1
votes

I have simple script for watchdog on network device. Script monitors response from PING command. If there is no answer then second thread executes and first thread is stopped. If second thread is finished then first thread is resumed (checking ping). If there is no answer then following message appears:

RuntimeError: threads can only be started once

Here is my code:

#!/usr/bin/python

import os
import time
import sqlite3
from ablib import Pin
import threading

led=Pin('W9','OUTPUT')

class threadout1(threading.Thread):
  def run(self):
    while True:
        conn = sqlite3.connect('database/database.db')
        cur = conn.cursor()
        cur.execute("SELECT * FROM watchdog")
        rows_output = cur.fetchall()
        time.sleep(1)
  
        if rows_output[0][1] == "ping":
            response = os.system("ping -c 1 " + rows_output[0][2])
            if response != 0:
                print "bad"
                rest.start()
                rest.join()     
    
class restart(threading.Thread):
  def run(self):
    led.on()
    time.sleep(15)
    led.off()
  
thr = threadout1()
rest = restart()
thr.start()
1
Why would you stop and restart the threads instead of always having one idling?jsfan
Why do you use a second thread at all if you wait for it to finish? You could just call a method from threadout1.Jasper

1 Answers

6
votes

You can either create the restart thread every time you need it

if response != 0:
print "bad"
restart_thread = restart()
restart_thread.start()
restart_thread.join()

or use Events

class restart_thread(threading.Thread):
  def __init__(self, evt):
    self.evt = evt

  def run(self):
    self.evt.wait()
    # do stuff
    self.evt.clear()

class threadout(threading.Thread):
  def __init__(self, evt):
    self.evt = evt

  def run(self):
    if #other thread needs to run once
      self.evt.set()

evt = threading.Event()
restart_thread = restart(evt)
restart_thread.start()
pinging_thread = threadout(evt)
pinging_thread.start()

To make the pinging_thread wait for the restart_thread to finish, you could use another Event.