How do I catch an Interrupt signal in Python when inside a blocking boost c++ method?
<p>I have a toolset which has been written in C++, and given Boost bindings for Python.</p>

<p>Initially, this code was all C++, and I caught a <kbd>CTRL</kbd>+<kbd>C</kbd> interrupt with:</p>

<pre><code>signal( SIGINT, signalCallbackHandler );
</code></pre>

<p>and</p>

<pre><code>void signalCallbackHandler(int /*signum*/)
{
    g_myObject-&gt;stop();
}
</code></pre>

<p>This worked fine.</p>

<p>However, now I've added the Python bindings in, I'm using Python to initialise the objects.</p>

<p>My initial thought was to do it like this:</p>

<pre><code>import signal

def handle_interrupt( signum, frame ) :
    g_myObject.stop()

signal.signal( signal.SIGINT, handle_interrupt )
g_myObject = MyObject()
g_myObject.start()
</code></pre>

<p>However, this signal handler is never called.</p>

<p>How should I be handling an interrupt like this? Do I need to do it inside C++, and then call the Python function from there?</p>

<p>I have <em>a</em> solution that works for this, although it'd be cleaner if I could get the signal caught in Python rather than C++.</p>

<p>One thing I didn't mention before is that MyObject is a singleton, so I'm getting it with <code>MyObject.getObject()</code></p>

<p>In Python, I've got:</p>

<pre><code>def signalHandler( signum ) :
    if signum == signal.SIGINT :
        MyObject.getObject().stop()

def main() :
    signal.signal( signal.SIGINT, handle_interrupt )

    myObject = MyObject.getObject()
    myObject.addSignalHandler( signal.SIGINT, signalHandler )
    myObject.start()
</code></pre>

<p>In my C++ code, in an area that shouldn't know anything about Python, I have:</p>

<pre><code>class MyObject
{
    public :
        void addSignalHandler( int signum, void (*handler)( int, void* ), void *data = nullptr );
        void callSignalHandler( int signum );
    private :
        std::map&lt;int, std::pair&lt;void (*)( int, void* ), void*&gt; &gt; m_signalHandlers;
}

void signalCallbackHandler( int signum )
{
    MyObject::getObject()-&gt;callSignalHandler( signum );
}

void MyObject::addSignalHandler( int signum, void (*handler)( int, void* ), void *data )
{
    m_signalHandlers.insert( std::pair&lt;int, std::pair&lt;void (*)( int, void* ), void *&gt; &gt;( signum, std::make_pair( handler, data ) ) );
    signal( signum, signalCallbackHandler );
}

void MyObject::callSignalHandler( int signum )
{
    std::map&lt;int, std::pair&lt;void (*)( int, void* ), void*&gt; &gt;::iterator handler = m_signalHandlers.find( signum );
    if( handler != m_signalHandlers.end() )
    {
        handler-&gt;second.first( signum, handler-&gt;second.second );
    }
}
</code></pre>

<p>And then in my Python bindings:</p>

<pre><code>void signalHandlerWrapper( int signum, void *data )
{
    if( nullptr == data )
    {
        return;
    }

    PyObject *func = (PyObject*)( data );
    if( PyFunction_Check( func ) )
    {
        PyObject_CallFunction( func, "i", signum );
    }
}

void addSignalHandlerWrapper( MyObject *o, int signum, PyObject *func )
{
    Py_INCREF( func );
    if( PyFunction_Check( func ) )
    {
        o-&gt;addSignalHandler( signum, &amp;signalHandlerWrapper, func );
    }
}
</code></pre>

<p>What I don't have, which I should add, is something in addSignalHandlerWrapper() that will check if there was already something fo that signal number, and if so, get it and decrement the reference before adding the new one. I haven't done this yet, as this functionality is only used for ending the program, but for completeness, it should be put in place.</p>

<p>Anyway, as I said at the start, this is more involved than it could be. It also only works as I have a singleton that can keep track of the function pointers.</p>

python c++ boost