From: Thomas Jollans on
On 07/19/2010 07:28 PM, Scott McCarty wrote:
> All, I just want to understand the C/Python piece better because I am
> writing a tutorial on signals and I am using python to demonstrate. I
> thought it would be fun to show that the SIGKILL is never processed, but
> instead python errors out. There is something in Python checking the
> SIGKILL signal handler, while not checking SIGTERM and I can't find the
> Python C code that handles it. When I am writing something like this, I
> like to point out the C code, not just cite the documentation (I did
> find this change in behaviour noted in the Python change log).

You cannot handle SIGKILL. Nothing to do with Python. Let me demonstrate:

0:pts/8:/tmp% cat sig.c
#include <signal.h>
#include <stdio.h>

void handle_sig(int sig)
{
printf("SIGNAL: %d\n", sig);
}

int main(int argc, char **argv)
{
if (signal(SIGUSR1, handle_sig) == SIG_ERR)
printf("failed to set for USR1\n");
if (signal(SIGTERM, handle_sig) == SIG_ERR)
printf("failed to set for TERM\n");
if (signal(SIGKILL, handle_sig) == SIG_ERR)
printf("failed to set for KILL\n");

for(;;);
}

0:pts/8:/tmp% cc -osig sig.c
0:pts/8:/tmp% ./sig
failed to set for KILL
^C
130:pts/8:/tmp%

>
> I have searched everywhere (mostly the code and a little google) and I
> cannot understand where the SIGKILL signal gets checked when it is set
> as a handler. I have scoured the Modules/signalmodule.c only to find two
> instances of the RuntimeError exception, but I cannot understand how
> python knows when a handler is set for SIGKILL. I understand that this
> changed in 2.4 and I am not trying to change it, I just really want to
> understand where this happens. I used grep to find SIGKILL and SIGTERM
> to see if I could determine where the critical difference is, but I
> cannot figure it out.
>
> I have about 2 hours of searching around and I can't figure it out, I
> assume it has to rely on some default behaviour in Unix, but I have no
> idea. I don't see a difference between SIGKILL and SIGTERM in the python
> code, but obviously there is some difference. I understand what the
> difference is in Unix/Linux, I just want to see it in the python code.
> Since python is checking at run time to see what signals handlers are
> added, I know there must be a difference. I am not asking about the
> signals, I understand them, I am asking about the registration of the
> SIGNAL handler and how it knows that you are trying to register SIGKILL,
> you get an error like this.
>
> ./signal-catcher.py
> Traceback (most recent call last):
> File "./signal-catcher.py", line 22, in <module>
> signal.signal(signal.SIGKILL, signal_handler_kill)
> RuntimeError: (22, 'Invalid argument')
>
> And the code is very simple, this attempts to register a handler for
> SIGKILL, but python knows and won't let you.
>
> signal.signal(signal.SIGKILL, signal_handler_kill)
>
> Please can someone just point me in the right direction.
>
> Thank You
> Scott M
>

From: Antoine Pitrou on

Hello,

> I am not asking about the signals, I understand them,
> I am asking about the registration of the SIGNAL handler and how it knows
> that you are trying to register SIGKILL, you get an error like this.
>
> ./signal-catcher.py
> Traceback (most recent call last):
> File "./signal-catcher.py", line 22, in <module>
> signal.signal(signal.SIGKILL, signal_handler_kill)
> RuntimeError: (22, 'Invalid argument')

>>> import errno
>>> errno.errorcode[22]
'EINVAL'

EINVAL is the error returned by the standard POSIX signal() function
when trying to register a handler for SIGKILL. As the signal() man page
says:

[...]
The signals SIGKILL and SIGSTOP cannot be caught or ignored.
[...]
ERRORS
EINVAL signum is invalid.


So, in short, Python doesn't check SIGKILL by itself. It's just
forbidden by the underlying C standard library, and Python propagates
the error as a RuntimeError.

Regards

Antoine.


From: Nobody on
On Mon, 19 Jul 2010 20:06:16 +0200, Antoine Pitrou wrote:

> So, in short, Python doesn't check SIGKILL by itself. It's just
> forbidden by the underlying C standard library,

Actually, it's forbidden by the kernel. The C library just passes along
the error to Python, which just passes it to the application.