Wangmaster
Posts: 10
Joined: Wed Nov 27, 2019 2:42 am

signal.pause() cannot detect SIGINT

Tue Dec 10, 2019 5:47 am

I'm following a stackoverflow answer (https://stackoverflow.com/questions/111 ... -in-python) and I'm trying to run the following simple code to trigger a signal handler on pressing ctrl-c:

Code: Select all

import signal
import sys

def signal_handler(sig, frame):
        print('You pressed Ctrl+C!')
        sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)

print('Press Ctrl+C')
signal.pause()
This doesn't work, it just continues pausing even after ctrl-c is hit.

Doing a bit of research, I found some documentation on signal which suggests the signal might not be captured:
A long-running calculation implemented purely in C (such as regular expression matching on a large body of text) may run uninterrupted for an arbitrary amount of time, regardless of any signals received. The Python signal handlers will be called when the calculation finishes.
So, I changed the signal.pause() for an infinite while loop as so:

Code: Select all

import signal
import sys

def signal_handler(sig, frame):
        print('You pressed Ctrl+C!')
        sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)

print('Press Ctrl+C')
while True:
	a = 0
This works as expected, and pressing ctrl-c terminates the program normally.

However, this is non-blocking code, and it defeats the purpose of signal.pause(), which has the explicit purpose of blocking until a signal is received.

Can someone tell me why the example given isn't working?

User avatar
thagrol
Posts: 2097
Joined: Fri Jan 13, 2012 4:41 pm
Location: Darkest Somerset, UK
Contact: Website

Re: signal.pause() cannot detect SIGINT

Tue Dec 10, 2019 4:06 pm

Umm doesn't python trap CTR-C and raise a KeyboardInterrupt exception? As such I'd expect that your code never sees the underlying signal and exits due to the unhandled exception.
Attempts to contact me outside of thes forums will be ignored unless signed in triplicate, sent in, sent back, queried, lost, found, subjected to public enquiry, lost again, and finally buried in soft peat for three months and recycled as firelighters

User avatar
jojopi
Posts: 3103
Joined: Tue Oct 11, 2011 8:38 pm

Re: signal.pause() cannot detect SIGINT

Tue Dec 10, 2019 5:28 pm

Both programs seem fine. Are you running inside IDLE, or some other integrated development environment?

IDLE does not allocate a terminal (presumably because that would not be portable to Windows). So, instead of Linux signalling your process as soon as you press Ctrl+C, you have to wait until the next time IDLE happens to check for input events, and then it tries to fake the correct behaviour. Its handling of most other terminal-based features is similarly broken.

Wangmaster
Posts: 10
Joined: Wed Nov 27, 2019 2:42 am

Re: signal.pause() cannot detect SIGINT

Wed Dec 11, 2019 4:05 am

jojopi wrote:
Tue Dec 10, 2019 5:28 pm
Both programs seem fine. Are you running inside IDLE, or some other integrated development environment?

IDLE does not allocate a terminal (presumably because that would not be portable to Windows). So, instead of Linux signalling your process as soon as you press Ctrl+C, you have to wait until the next time IDLE happens to check for input events, and then it tries to fake the correct behaviour. Its handling of most other terminal-based features is similarly broken.
Was running under IDLE and Thonny. Per your suggestion, I ran them through command line and both scripts run as expected now, thanks.

I'm a bit puzzled as to the differences between running scripts through the IDLE shell and directly through the interpreter. I experienced similar problems with threading programs in shell whereby daemon threads didn't recognize the main thread as terminated and therefore wouldn't terminate themselves on closing the program. Can you point me to some resources explaining this difference?
thagrol wrote: Umm doesn't python trap CTR-C and raise a KeyboardInterrupt exception? As such I'd expect that your code never sees the underlying signal and exits due to the unhandled exception.
From what I understand, SIGINT is the signal sent for a keyboard interrupt, and it will be handled appropriately be the assigned signal handler. I'm using it as an alternative to a exception handler which will require multiple try-except statements.

Return to “Python”