作家
登录

一个Reentrant Error引发的对Python信号机制的探索和思考

作者: 来源: 2017-09-14 11:04:12 阅读 我要评论

疑云又起

不幸的是,我的猜想很快被颠覆了。

在翻看 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 函数,个中有如许一段代码:

  1. Handlers[sig_num].tripped = 1;      
  2.  
  3. if (!is_tripped) { 
  4.  
  5.     is_tripped = 1; 
  6.  
  7.     Py_AddPendingCall(checksignals_witharg, NULL); 
  8.  
  9.  

这段代码就是文档中所说的逻辑:做标记并延后 Python Signal Handler。个中 checksignals_witharg 即为被延后调用的函数,位于 192 行,核心代码只有一句:

  1. static int 
  2.  
  3. checksignals_witharg(void * unused) 
  4.  
  5.  
  6.     return PyErr_CheckSignals();  
  7.  
  8.  
  9. r_CheckSignals 位于 1511 行:  
  10.  
  11. int 
  12.  
  13. PyErr_CheckSignals(void)  
  14.  
  15.     int i;  
  16.     PyObject *f;   
  17.  
  18.     if (!is_tripped)  
  19.         return 0;  

  20.   推荐阅读

      CIO半月刊第十九期|李克强总理再提制造业转型,51CTO带你摸底制造业

    51CTO诚邀您9月23号和秒拍/国美/美团元专家一路聊智能CDN的优化之路,抓紧时光哦! 【编辑推荐】CIO半月刊第十四期|查访过30多位CIO,我们得出如许的结论CIO半月刊第十五期|某有名旅游企业>>>详细阅读


    本文标题:一个Reentrant Error引发的对Python信号机制的探索和思考

    地址:http://www.17bianji.com/lsqh/37408.html

关键词: 探索发现

乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

网友点评
自媒体专栏

评论

热度

精彩导读
栏目ID=71的表不存在(操作类型=0)