0

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?

2
  • hi, did you ever manage to solve this issue? Commented Dec 20, 2016 at 7:39
  • @ShiftyScales my apologies, I don't remember the details. Most likely I used some mixed solution from the answer below and some other code. Commented Dec 20, 2016 at 10:53

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.