I would better start the question from the code.
from multiprocessing import Process, Event, Queue
from threading import Timer
from Queue import Empty
class MyServer(Process):
def __init__(self, port, queue):
Process.__init__(self)
self.port = port
self.queue = queue
self.sd = None
def run(self):
try:
self.start_serving()
except KeyboardInterrupt:
print("Shutting down..")
finally:
if self.sd is not None:
self.sd.close()
def start_serving(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sd = s
try:
s.bind(('', self.port))
s.listen(1)
while True:
conn, addr = s.accept()
while True:
# I dont want to bore you with excess code
# just recv data from clients
try:
msg = self.queue.get_nowait()
# here i start Timer with delay from message (I'll describe Message class below)
Timer(msg.delay, self.response_handler, args=(conn, msg)).start()
except Empty:
pass
conn.close()
finally:
s.close()
def response_handler(self, sd, msg):
# doesn't matter
# and now I want to terminate the MyServer instance
if msg.terminate:
# the problem is here. Lets call it 'problem line'
sys.exit()
msg
is instance of Message
class which is:
class Message(object):
def __init__(self, port, delay, values, terminate=False):
self.port = port
self.delay = delay
self.values = values
self.terminate = terminate
The logic is I get data from clients via TCP connection and check Queue for message. Messages are things to control the server. Sometimes I get a message like "wait 3 seconds and terminate the server". What I have done so far.
self.terminate()
at the problem line
. I get AttributeError: 'NoneType' object has no attribute 'terminate'
problem line
. I assumed the exception was caught in run()
function. I was wrong sys.exit()
. It doesn't work too. Perhaps my question can be shorter. How to terminate the process from its thread in Python?
Why don't you use multiprocessing.Event
(you are already importing it) and exit the process gracefully if you get an terminate message.
To do this add this to __init__
:
self.exit = Event()
And change the two while
loops:
while True:
conn, addr = s.accept()
while True:
#...
to
while not self.exit.is_set():
conn, addr = s.accept()
while not self.exit.is_set()
#...
then in your response handler:
if msg.terminate:
self.exit.set()
this will allow the code to naturally exit the loops, ensuring that conn.close()
is called.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.