在一个阻塞boost c++方法中,如何在Python中捕捉中断信号?

2024-09-30 06:19:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个工具集,它是用C++编写的,并且为Python提供了升压绑定。在

最初,此代码都是C++,我捕获了 ctrl +kbd> c:用< /p>中断

signal( SIGINT, signalCallbackHandler );

以及

^{pr2}$

这很有效。在

但是,现在我已经在中添加了Python绑定,我正在使用Python初始化对象。在

我最初的想法是这样做:

import signal

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

signal.signal( signal.SIGINT, handle_interrupt )
g_myObject = MyObject()
g_myObject.start()

但是,这个信号处理程序永远不会被调用。在

我应该如何处理这样的中断?我需要在C++内部做它,然后从那里调用Python函数吗?在


Tags: 对象代码importsignaldef工具集handlectrl
2条回答
<>我有一个解决方案,虽然这能使我在Python中捕获到的信号比C++更干净。在

有一件事我之前没有提到,MyObject是一个单例对象,所以我用MyObject.getObject()来获得它

在Python中,我有:

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()

在我的C++代码中,在一个不知道Python的区域,我有:

^{pr2}$

然后在我的Python绑定中:

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->addSignalHandler( signum, &signalHandlerWrapper, func );
    }
}

我没有的是addSignalHandlerWrapper()中的某些内容,它将检查该信号号是否已经存在某些内容,如果存在,则获取它并在添加新信号之前递减引用。我还没有这样做,因为这个功能只用于结束程序,但为了完整性,它应该放在适当的位置。在

不管怎样,正如我在一开始所说的,这件事比它可能涉及的更多。它也只在我有一个可以跟踪函数指针的singleton时工作。在

不会调用您的python信号处理程序,因为python会将信号处理程序的执行推迟到下一个字节码指令执行之后—请参见the library documentation for signal, section 18.8.1.1

A Python signal handler does not get executed inside the low-level (C) signal handler. Instead, the low-level signal handler sets a flag which tells the virtual machine to execute the corresponding Python signal handler at a later point(for example at the next bytecode instruction). This has consequences:

  • It makes little sense to catch synchronous errors like SIGFPE or SIGSEGV that are caused by an invalid operation in C code. Python will return from the signal handler to the C code, which is likely to raise the same signal again, causing Python to apparently hang. From Python 3.3 onwards, you can use the faulthandler module to report on synchronous errors.
  • 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.

这样做的原因是,信号可以在任何时候到达,可能在python指令执行的一半时间到达。VM开始执行信号处理程序是不安全的,因为VM处于未知状态。因此,python安装的实际信号处理程序只设置一个标志,告诉VM在当前指令完成后调用信号处理程序。在

如果信号在C++函数执行期间到达,则信号处理程序设置标志并返回到C++函数。在

如果信号处理程序的主要目的是允许C++函数被中断,那么我建议您放弃Python信号处理程序,并安装一个C++信号处理程序,它设置一个标志,该标志触发C++代码中的早期退出(可能返回一个指示中断的值)。在

这种方法允许你使用相同的代码,不管你是用Python、C++或是另一个绑定调用你的代码。在

相关问题 更多 >

    热门问题