
疑云又起
不幸的是,我的猜想很快被颠覆了。
在翻看 Python signal 模块的官方文档,我看到了如下论述:
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).
— via Python Documentation
也就是说,Python 中应用 signal.signal 注册的旌旗灯号处理函数并不会在收到旌旗灯号时急速履行,而只是简单做一个标记,将其延迟至之后的某个机会。这么做可以尽量快地停止异常控制流,削减其对被阻拒却程的影响。
这番表述可以说是颠覆了我的猜想,因为 Signal Handler 中的 print 并没有在异常控制流中履行。那异常又是怎么产生的呢?
文档说 Python Signal Handler 会被延后至某个机会进行,但并没有明示是什么时刻。对于这个疑问,这个提问的被采取答复 则斩钉截铁地将其具体化到了“某两个 Python 字节码之间”。
我们知道,Python 法度榜样在履行前会被编译成 Python 内定的字节码
(bytecode),Python 虚拟机实际履行的┞俘是这些字节码。假使该答复是精确的,则立即竽暌剐如下推论:在处理旌旗灯号的过程中,字节码具有原子性(atomic)。也就是说,主线程老是在两个字节码之间决定是否转移控制流, 而 不会 出现以下情况:


是以,除了在两个字节码之间,应当还有其他机会唤起了 Python Signal Handler。
至此,问题已触及 Python 的地板了,需向更底层发掘才能找到谜底。
深刻源码
而 PyErr_CheckSignals 在 Python 源码中出现了 80 多处,遍布 Python 的各个模块中——这解释该答复的另一半说法是缺点的:除了在两个字节码之间,Python 还可能在其他角落唤起 Python Signal Handler。个中有两处值得留意,它们都位于 Modules/_io/bufferedio.c 中:
- 1884 行的 _bufferedwriter_flush_unlocked
- 1939 行的 _io_BufferedWriter_write_impl
旌旗灯号注册逻辑位于 Modules/signalmodule.c 文件中。 313 行的 signal_handler 是旌旗灯号处理函数的最外层包装,由体系调用 signal 或 sigaction 注册至内核,并在旌旗灯号产生时被内核回调,是异常控制流的人口。signal_handler 重要调用了 239 行处的 trip_signal 函数,个中有如许一段代码:
- Handlers[sig_num].tripped = 1;
- if (!is_tripped) {
- is_tripped = 1;
- Py_AddPendingCall(checksignals_witharg, NULL);
- }
这段代码就是文档中所说的逻辑:做标记并延后 Python Signal Handler。个中 checksignals_witharg 即为被延后调用的函数,位于 192 行,核心代码只有一句:
- static int
- checksignals_witharg(void * unused)
- {
- return PyErr_CheckSignals();
- }
- r_CheckSignals 位于 1511 行:
- int
- PyErr_CheckSignals(void)
- {
- int i;
- PyObject *f;
- if (!is_tripped)
- return 0;
推荐阅读
CIO半月刊第十九期|李克强总理再提制造业转型,51CTO带你摸底制造业
51CTO诚邀您9月23号和秒拍/国美/美团元专家一路聊智能CDN的优化之路,抓紧时光哦! 【编辑推荐】CIO半月刊第十四期|查访过30多位CIO,我们得出如许的结论CIO半月刊第十五期|某有名旅游企业>>>详细阅读
本文标题:一个Reentrant Error引发的对Python信号机制的探索和思考
地址:http://www.17bianji.com/lsqh/37408.html
1/2 1

网友点评
精彩导读
科技快报
品牌展示