title: How to handle KeyboardException raised in threading module?
body: <p>I'm creating a server using the <code>socket</code> and <code>threading</code> module. The server allows for multiple connections to be made. I've been doing some error handling (as shown in the code below). However, there is one error that I cannot figure out how to handle.</p>
  
  <p><strong>Code (server.py):</strong></p>
  
  <pre><code>import socket
  import threading
  # import pyaudio
  # import json
  from os import system
  
  system('clear')
  
  host = socket.gethostbyname(socket.gethostname())
  port = 5000
  buffer_size = 2048
  connected_clients = {}
  
  
  # Thread for listening and accepting new connections
  def client_listener():
      while True:
          try:
              # Accepts new client
              connection, address = server_socket.accept() 
  
              # Creates a new thread for each connected client
              handle_client_thread = threading.Thread(target=handle_client, args=(connection, address))
              handle_client_thread.start()
          except ConnectionAbortedError:
              pass
          except OSError:
              pass
          except KeyboardInterrupt:
              pass
  
  
  # Handles each connected client in a separate thread
  def handle_client(client, client_address):
      try:
          # Receives room number
          room_number = client.recv(buffer_size).decode('utf-8')
          print(f'\nConnection from {client_address[0]}:{client_address[1]} ({room_number})')
  
          # Adds new client to 'connected_clients'
          connected_clients[room_number] = client
          print(connected_clients)
  
          while True:
              data = client.recv(buffer_size).decode('utf-8')
              # If no data is received, close the socket
              if not data:
                  print(f'{client_address[0]}:{client_address[1]} ({room_number}) Disconnected')
                  connected_clients.pop(room_number)
                  break
              # Print received data
              else:
                  print(f'{client_address[0]} ({room_number}): {data}')
      except KeyboardInterrupt:
          client.close()
          connected_clients.pop(room_number)
  
  
  with socket.socket() as server_socket:
      try:
          # Prevents [Errno 48: Address already in use]
          server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  
          # Binds socket to host and port
          server_socket.bind((host, port))
          server_socket.listen()
          print(f'Server hosted on {host}:{port}')
  
          # Starts new thread for listening for new clients
          client_listener_thread = threading.Thread(target=client_listener, name=client_listener)
          client_listener_thread.start()
  
          # Prevents main thread from closing
          while True:
              pass
      except socket.error as error_message:
          print(str(error_message))
      except KeyboardInterrupt:
          print(': Closing server...\n')
          pass
  </code></pre>
  
  <p>The error message is raised when I close the server with a keyboard interrupt (^C). When I first press ^C, the server is closed. However, the second ^C seems to raise an exception within the <code>threading</code> module.</p>
  
  <p><strong>Error message:</strong> </p>
  
  <pre><code>Server hosted on 10.108.249.108:5000
  ^C: Closing server...
  
  ^CException ignored in: &lt;module 'threading' from '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py'&gt;
  Traceback (most recent call last):
    File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 1273, in _shutdown
      t.join()
    File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 1032, in join
      self._wait_for_tstate_lock()
    File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 1048, in _wait_for_tstate_lock
      elif lock.acquire(block, timeout):
  KeyboardInterrupt
  </code></pre>
  
  <p>How would I go about handling this KeyboardInterrupt in a seamless way such that the program is closed without errors on a single ^C? The desired result would be having the server close the connections with each connected client, close the threads, then finally shut down the server itself.</p>