简体   繁体   中英

Terminating process from Timer thread

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.

  1. Call self.terminate() at the problem line . I get AttributeError: 'NoneType' object has no attribute 'terminate'
  2. Raise an exception at the problem line . I assumed the exception was caught in run() function. I was wrong
  3. Call 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM