1

I have just written a very simple udp chatting program for fun. It worked as supposed but now I have no ideas how to safely exit it. It seems that calling sys.exit() is not acceptable due to the problem here: Why does sys.exit() not exit when called inside a thread in Python?

Simply raising signals by ctrl + c will fail because it will be intercepted by raw_input().

Is there any decent way to deal with it?

Here is my code snippet:

import socket
import threading

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  
address = ('192.168.1.xxx', 31500)  
target_address = ('192.168.1.xxx', 31500)
s.bind(address)  

print('waiting for input...')

def rcv():
    while True:
        data, addr = s.recvfrom(2048)  
        if not data:            
            continue
        print 'Received: #### ', data
        print '\n'

def send():
    while True:
        msg = raw_input()
        if not msg:
            continue
        s.sendto(msg, target_address)

t1 = threading.Thread(target = rcv)
t2 = threading.Thread(target = send)

t1.start()
t2.start()
Community
  • 1
  • 1
alvinzoo
  • 493
  • 2
  • 8
  • 17

1 Answers1

0

Replacing my previous answer: I modified your code to:

import socket
import threading

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  
address = ('192.168.1.xxx', 31500)  
target_address = ('192.168.1.xxx', 31500)
s.bind(address)  

EXIT_MSG_GUARD = "@Quit!"
print('waiting for input...')

def rcv():
    while True:
        data, addr = s.recvfrom(2048)  
        if not data:            
            continue
        print 'Received: #### ', data
        print '\n'

def send():
    while True:
        msg = raw_input()
        if not msg:
            continue
        else:
            s.sendto(msg, target_address)
            if msg == EXIT_MSG_GUARD:
                return

t1 = threading.Thread(target = rcv)
t2 = threading.Thread(target = send)

t1.setDaemon(True)

t1.start()
t2.start()

There are 2 things that I did:

  • Add a message guard (in my example @Quit!, but you can change it to anything you like): when the user inputs that text, after sending it, the t2 thread ends.
  • Make thread t1 daemonic, meaning that when the main thread and all the non daemon threads will end, this will end too, and the program will exit.

Note: Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly. If you want your threads to stop gracefully, make them non-daemonic and use a suitable signalling mechanism such as an Event.

As an alternative to daemon threads, you could use the solution posted here (beware of the limitations as well!). It is nicer (and recommended) but, will require more work including a little bit of change to your rcv function

Community
  • 1
  • 1
CristiFati
  • 38,250
  • 9
  • 50
  • 87