Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 04 Mar 2013 11:21:16 +0200
From:      Andriy Pylypenko <bamby@sippysoft.com>
To:        Pavel Perestoronin <eigenein@gmail.com>
Cc:        freebsd-ports-bugs@freebsd.org
Subject:   Re: SIgnal delivery to child threads is blocked in Python 2.x
Message-ID:  <5134678C.10202@sippysoft.com>
In-Reply-To: <CANbiqPbKRvNZQnoCKO=De8C03R2Y1YWf-3oofLzwe4LpcSzHrQ@mail.gmail.com>
References:  <CANbiqPbKRvNZQnoCKO=De8C03R2Y1YWf-3oofLzwe4LpcSzHrQ@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On 01.03.13 16:52, Pavel Perestoronin wrote:
> Hello,
>
> I think there is an issue caused by the following patch: http://svnweb.freebsd.org/ports/head/lang/python27/files/patch-Python_thread__pthread.h?view=log
>
> The patch ensures a signal is delivered to the main thread always. This makes impossible to send a signal to a child process that is spawned by a child thread. This can be shown on the following script that works differently in FreeBSD and Linux:
>
[skip]
>
> There is also the comment to the patch:
>
>> Make sure the singal is delivered to the main thread, where python
> runs its signal handlers, not to a random thread that happens to be
> executing at the time when signal arrives. This functionality has been
> lost since Python 2.3, possible cause is that the linux implementation
> of POSIX threads always delivered signal to the main thread. This
> bug results in rather annoying inability to terminate threading script
> with ^C for example and there could be other issues as well.
>
> But on Linux child threads has no signals blocked and according to Linux man signal(7):
>
>> If more than one of the threads has the signal unblocked, then the kernel chooses an arbitrary thread to which to deliver the signal.
>
> Anyway, the patch makes Python scripts that use threading work differently in FreeBSD and Linux.

Hi Pavel,

But yes of course the patch ensures exactly the behaviour you're 
complaining about.

The POSIX does not define which thread the signal should be delivered 
to. The Linux always delivers signals to the main thread and FreeBSD 
chooses a random thread and both behaviours are POSIX conforming. 
However Python 2.x cannot handle signals coming from non-main threads 
correctly and this is worsened by the fact the Python 2.x does not have 
signal mask manipulation procedures in standard library. This is why 
this patch was created.

If you want to create a portable and standards conforming code, you can 
use Python 3. Its standard library supports the pthread_sigmask() & 
friends and it does not include this patch and never will.

Under Python 2.x I would suggest to unblock the signals using the 
ctypes. Below is your code with an example of such workaround:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from ctypes import CDLL, Structure, sizeof, c_ulong, pointer
from platform import system
import threading

SIGSET_NWORDS = 1024 / (8 * sizeof(c_ulong))
class SIGSET(Structure):
     _fields_ = [
         ('val', c_ulong * SIGSET_NWORDS)
     ]

if system() == "FreeBSD":
     libc = CDLL('libc.so')
     pthread_sigmask = libc.pthread_sigmask
     SIG_BLOCK = 1
     SIG_UNBLOCK = 2
     SIG_SETMASK = 3
else:
     libc = CDLL("libc.so.6")
     libpthread = CDLL("libpthread.so.0")
     pthread_sigmask = libpthread.pthread_sigmask
     SIG_BLOCK = 0
     SIG_UNBLOCK = 1
     SIG_SETMASK = 2

def test():
     sigset = SIGSET()
     old_sigset = SIGSET()
     libc.sigemptyset(pointer(sigset))
     for i in range(1, 33):
         libc.sigaddset(pointer(sigset), i)
     pthread_sigmask(SIG_UNBLOCK, pointer(sigset), pointer(old_sigset))
     print "sigblock is "
     print libc.sigblock(0)  # Linux and FreeBSD show 0 here
     # start new process here

     pthread_sigmask(SIG_SETMASK, pointer(old_sigset), None) # restore 
sigmask
     print "sigblock is "
     print libc.sigblock(0)  # Linux shows 0, while FreeBSD shows 2147417855

if __name__ == "__main__":
     threading.Thread(target=test).start()


   Kind regards,
   Andriy Pylypenko



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?5134678C.10202>