2

I'm wanting to exit an UDP-server on KeyboardInterrupt, but this is not working immediately. when doing some research I stumbled on this question, where someone suggests that it is a issue with the GIL. Python processes calling into C APIs can block the Python interpreter from processing the interrupt. is there any way the unblock this in python?

the code I have is the following:

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:      #works after new data is send to server
        print('Interrupted', file=sys.stderr)
        try:
            sys.exit(0)
        except SystemExit:
            os._exit(0)

main:

def main():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server_address = ('localhost', 2000)
    s.bind(server_address)

    running = True
    print('Ready for connection')
    while running:
        try:
            msg = ""
            data, address = s.recvfrom(2000)    #look for timeout and interrupt
            msg = data.decode('utf-8')
            if not data:
                    break
            print(f'received {msg}')
            if msg[:5] == "PING-":
                print('sending PONG back to the client')
                message = 'PONG-' + msg[5:len(msg)]
                s.sendto(message.encode('utf-8'), address)
            else:
                print('bad format')
        except socket.error as socketerror:
            print(f'Error:  {socketerror}', file=sys.stderr)
    s.close()

When i'm not running the client and press ctrl-c nothing happens, the program just does nothing. When I start up the client and send a UDP message, the interrupt is perfectly handled when the server gets a UDP message from the client. The UDP message then is dropped and the client handles it as a timeout. After the timeout the client has a lost connection.

The goal is to get the server exit even without the client running and without using ctrl-break.

Dries Jans
  • 107
  • 1
  • 11
  • Could you share the contents of your `main()`? It's possible that something inside the main is catching or blocking the `KeyboardInterrupt` from getting properly raised. As a general solution, you may want to look into using signals like [this](https://www.g-loaded.eu/2016/11/24/how-to-terminate-running-python-threads-using-signals/) example. – Andrew F Oct 15 '19 at 12:43
  • The issue you linked was fixed. If you look in the comments you will see a PR was merged that fixed that issue. I don't know what you are all tying to do (because the code isn't complete) so I can't really help you. Please add enough code to make a minimum **running** example. Also you should just call `exit()`, dont call `sys.exit...` nor `os._exit...`. – Error - Syntactical Remorse Oct 15 '19 at 12:43
  • @AndrewF I added the main to the question – Dries Jans Oct 15 '19 at 12:45
  • The Python team has been trying to eliminate the GIL for years without success. It's doubtful it would be easy to work around. – Mark Ransom Oct 15 '19 at 12:46
  • @DriesJans could you also include your `python --version`? It looks like since 3.5 [`recvfrom`](https://docs.python.org/3/library/socket.html#socket.socket.recvfrom) has a new behavior with interruptions. Running `3.7.4` I cannot reproduce the issue. – Andrew F Oct 15 '19 at 12:58
  • @AndrewF I'm also running 3.7.4 and the code is executed with Powershell – Dries Jans Oct 15 '19 at 13:31
  • on `KeyboardInterrupt` you should try to close the connection, this is also how to bypass the `GIL`, by defining handlers to catch the signals and stop (preferably gracefully) the process – shahaf Oct 15 '19 at 15:06
  • @shahaf should I move the KeyboardInterrupt to inside the main and then close the socket inside the keyboardinterrupt? – Dries Jans Oct 15 '19 at 15:54

0 Answers0