0

I'm writing a port scanning program in python everything works fine but I wanted to implement crtl+c interrupt function to terminate the program it stops the main program but there are threads still running. How to terminate the program completely using the ctrl+c keys?

class StatusChecker(threading.Thread):
    """
    The thread that will check HTTP statuses.
    """

    #: The queue of urls
    url_queue = None

    #: The queue our results will go into
    result_queue = None

    #: An event that tells the thread to stop
    stopper = None

    def __init__(self, url_queue, result_queue, stopper):
        super().__init__()
        self.url_queue = url_queue
        self.result_queue = result_queue
        self.stopper = stopper

    def run(self):
        print_lock = threading.Lock()
        while not self.stopper.is_set():
            try:
                # this will throw queue.Empty immediately if there's
                # no tasks left
                to_check = self.url_queue.get_nowait()
            except queue.Empty:
                break # empty queue, we're done!
            else:
                with print_lock:
                    print(to_check,' ')
                self.url_queue.task_done() # the the queue we're done


class SignalHandler:
    """
    The object that will handle signals and stop the worker threads.
    """

    #: The stop event that's shared by this handler and threads.
    stopper = None

    #: The pool of worker threads
    workers = None

    def __init__(self, stopper, workers):
        self.stopper = stopper
        self.workers = workers

    def __call__(self, signum, frame):
        """
        This will be called by the python signal module

        https://docs.python.org/3/library/signal.html#signal.signal
        """
        self.stopper.set()

        for worker in self.workers:
            worker.join()

        sys.exit(0)


if __name__ == '__main__':
    # all the variables we'll need
    num_workers = 2
    stopper = threading.Event()
    result_queue = queue.Queue()
    url_queue = queue.Queue()

    # populate our work queue
    for i in range(65535):
        url_queue.put(i)

    # we need to keep track of the workers but not start them yet
    workers = [StatusChecker(url_queue, result_queue, stopper) for i in range(num_workers)]

    # create our signal handler and connect it
    #handler = SignalHandler(stopper, workers)
    #signal.signal(signal.SIGINT, handler)

    # start the threads!
    for i, worker in enumerate(workers):
        print('Starting worker {}'.format(i))
        worker.daemon = True
        worker.start()

    # wait for the queue to empty
    try:
        while threading.active_count() > 0:
            time.sleep(0.1)
    except:
        sys.exit(0)
    while not result_queue.empty():
        url, status = result_queue.get_nowait()
        print('{} - {}'.format(url, status))
PNC
  • 357
  • 1
  • 5
  • 19

1 Answers1

0

Threads share the same memory space as the main process. So technically doing ctrl-c on the main process should deallocate the thread memory. If the threads are in the middle of writing then it could be unsafe, but otherwise it should be ok. Otherwise you can use python's signal library and create a signal handler to trap a SIGINT.

Max Paymar
  • 588
  • 1
  • 7
  • 23