5

I can currently handle CTRL+C via:

def hand_inter(signum, frame):
    print 'hey, nice job.'

signal.signal(signal.SIGINT, hand_inter)

However I am required to also handle CTRL+D yet cannot find the appropriate "signal.CTRL+D" call for signum.

Mwiza
  • 7,780
  • 3
  • 46
  • 42

1 Answers1

3

Ctrl+D is not a signal, it's end of file.

If you have an interactive program, you will be most probably reading STDIN and Ctrl+D is way how user says that the input is over. Outside this context it does not have any special meaning.

The code that executes after that is typically the code after "readline" or similar call. This is equivalent to reading any other file and detecting it has ended and there is no more data to read--the corresponding call will give you indication of that.

For example, this could be a simple interactive program:

import sys

while True:
    line = sys.stdin.readline()    # readline will return "" on EOF
    if line:
        do_something_with(line)    # * if user just pressed Enter line will
                                   #   be "\n", i.e. still True
    else:                          # * user pressed C-D, i.e. stdin has been
        sys.exit(0)                #   closed readline call must have returned ""

On the other hand, Ctrl+C is different, it's way how user tells their terminal to terminate the running process. It can come at any moment, regardless if the process ever asks for input or even cares about outside world.

Because the process has no way of expecting this you need signal to set up so-called traps, which is mechanism provided by the OS to enable processes say, "if you ever want to terminate me, please just execute this instead..." (which could be anything including nothing, i.e. just ignoring the signal). Exceptions are special signals like SIGKILL, which can't be caught by the process.

Mwiza
  • 7,780
  • 3
  • 46
  • 42
Alois Mahdal
  • 10,763
  • 7
  • 51
  • 69
  • I am implementing a chat server with client code that is actively listening while connected and sends a message when 'enter' is pressed. I am required to terminate the connection with a 'CTRL-D' command. –  Mar 07 '14 at 17:57
  • @JoeyDiNardo look at my example. (Expect bugs since I wrote it from head but you get the idea... :)) – Alois Mahdal Mar 07 '14 at 18:07
  • Hm, with sys.exit(), pressing ctrl+d doesn't seem to do anything at all. When I set it to "print 'test'", it works flawlessly. I have it in a separate thread, could that be the issue? `msg = sys.stdin.readline() if msg: s.send(msg) prompt() else: sys.exit()` –  Mar 07 '14 at 18:26
  • strange, I just copied my code, added do_something... and it works fine. Maybe try writing a simple text file and sending it to the stdin using shell redirection like `./script.py < simple_file.txt` – Alois Mahdal Mar 07 '14 at 18:32
  • Well if you use threads (and since you say it's for networking I guess you use the Python's threaded TCP server), the original code might not work since for example a thread could wait for another one etc ... gets little bit complicated. :) – Alois Mahdal Mar 07 '14 at 18:38
  • Fixed it with os._exit(0) instead of sys. Thanks again :). –  Mar 07 '14 at 18:39
  • I'm not sure what's the proper way in your case but I know that `os._exit(0)` is not recommended. For example it probably won't clean up properly so you might have other problems like file debris or ocuppied sockets if quitting and starting the process often (it depends a lot on your OS). – Alois Mahdal Mar 07 '14 at 18:44