willwade
willwade

Reputation: 2220

KeyboardInterrupt Threads

I'm writing a simple TCP socket server with pyBonjour support. To do this I figured using threading. The problem is how I get the server to stop... I figured the following should work (according to this) but it isn't

Is there a nicer way to do this (that works)..

import SocketServer
import threading
import pybonjour
import select
import time

class BonjourThread(threading.Thread):        
    def run(self):
        sdRef = pybonjour.DNSServiceRegister(name = 'MacroServer - Mac',
                                     regtype = '_macroserver._tcp',
                                     port = 12000,
                                     callBack = self.bonjour_register_callback)

        while True:
            ready = select.select([sdRef], [], [])
            if sdRef in ready[0]:
                pybonjour.DNSServiceProcessResult(sdRef)

    def bonjour_register_callback(self, sdRef, flags, errorCode, name, regtype, domain):
        if errorCode == pybonjour.kDNSServiceErr_NoError:
            print 'Bonjour started'


class TCPThread(threading.Thread):
    def run(self):
        try:
            HOST, PORT = "localhost", 12000
            server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
            print 'TCP server started'
            server.serve_forever()
        except KeyboardInterrupt:
            print 'Closing Down'
            exit()

class MyTCPHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        try:
            # self.request is the TCP socket connected to the client
            self.data = self.request.recv(1024).strip()
            print "{} wrote:".format(self.client_address[0])
            print self.data
            # just send back the same data, but upper-cased
            self.request.sendall(self.data.upper())
        except KeyboardInterrupt:
            print 'Closing Down'
            exit()

if __name__ == "__main__":
    try:
        thread1 = TCPThread()
        thread1.start()
        thread2 = BonjourThread()
        thread2.start()
        while True: time.sleep(100)
    except (KeyboardInterrupt, SystemExit):
        print 'Received keyboard interrupt, quitting threads.\n'
    finally:
        print 'And its bye from me'

Upvotes: 2

Views: 2002

Answers (2)

user3012759
user3012759

Reputation: 2095

from place you linked to:

thread.daemon=True causes the thread to terminate when the main process ends.

which you missed in your code, so that's why they don't stop

as to nicer ways to do it, you could create your own signal handler and terminate your threads but not sure if it's any nicer than:

thread.daemon=True

Upvotes: 2

tdelaney
tdelaney

Reputation: 77337

In python, only the main thread gets the KeyboardInterrupt signal. How you want to handle termination of your socket servers and their various clients can get complex. I've made logging servers where I kept the sockets in a master list, protected by a lock, and closed them all then waited for termination in the keyboard interrupt. You could even mark the threads as daemons and just exit - let the operating system clean up the sockets.

Upvotes: 2

Related Questions