作家
登录

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

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

这两个函数是 io.BufferedWriter 类的底层实现,会被 print 借居调用。细心不雅察可以发明,它们都有着类似的构造:

  1. ENTER_BUFFERED(self)  
  2. // ...  
  3. PyErr_CheckSignals();  
  4. // ...  
  5. LEAVE_BUFFERED(self)  

ENTER_BUFFERED 是一个宏,会测验测验申请无壅塞线程锁以包管函数不会被重入:

  1. #define ENTER_BUFFERED(self) \  
  2.     ( (PyThread_acquire_lock(self->lock, 0) ? \  
  3.        1 : _enter_buffered_busy(self)) \  
  4.      && (self->owner = PyThread_get_thread_ident(), 1) )  

至此,本相已经大年夜白了。

Python Signal Handler 的调用会被延后,但机会不止在两个字节码之间,而是可能涌如今任何处所。

本相

当旌旗灯号中断产生在 _bufferedwriter_flush_unlocked 或 _io_BufferedWriter_write_impl 中时,这两个函数中的 PyErr_CheckSignals 会直接唤起 Python Signal Handler,而此时由 ENTER_BUFFERED 上的锁尚未解开,若 Python Signal Handler 中又有 print 函数调用,则会导致再次 ENTER_BUFFERED 上锁掉败,大年夜而抛出异常。时序图如下:

  1. import sys 
  2.  
  3. import subprocess 
  4.  
  5. # ... 
  6.  
  7. celery_process = subprocess.Popen( 
  8.  
  9.     ['celery''-A''XXX''worker'], 
  10.  
  11.     stdout=subprocess.PIPE, 
  12.  
  13.     stderr=sys.stderr 
  14.  
  15.  
  16. try: 
  17.  
  18.     # Start and wait for server process 
  19.  
  20. except KeyboardInterrupt: 
  21.  
  22.     # Ctrl + C pressed 
  23.  
  24.     celery_process.terminate() 
  25.  
  26.     celery_process.wait()  

思虑

为什么不将 Python Signal Handler 调用的地点同一在一个处所,而是分布在法度榜样的遍地呢?浏览相干代码,我认为有两点原因:

旌旗灯号中断会使某些体系调用行动异常,大年夜而使体系调用的调用者不知若何处理,此时须要调用 Signal Handler 进行可能的状况恢复。一个例子是 write 体系调用,旌旗灯号中断会导致数据部分写回,与此相干的一大年夜批 I/O 函数(包含出问题的 _bufferedwriter_flush_unlocked 和 _io_BufferedWriter_write_impl)便只能响应地调用 PyErr_CheckSignals。

某些函数须要做计算密集型义务,为了防止 Python Signal Handler 的调用被过长地延后(其实主如果为了及时响应键盘中断,防止法度榜样无法早年台停止),必须合时地检查并调用 Python Signal Handler。一个例子是 Objects/longobject.c 中的诸函数,longobject.c 定义了 Python 特有的无穷长整型,其相干的运算可能耗时相当长,必须做如许的处理。

总结

解决

异常产生的机会有随机性

因为第一条,Python Signal Handler 中尽量都应用 可重入的 的函数,以避免奇怪的问题。可重人道可以大年夜文档获知,也可以结合定义由源码揣摸出来。

有疑问,翻源码。人会撒谎,代码不会。


  推荐阅读

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

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


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

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

关键词: 探索发现

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

网友点评
自媒体专栏

评论

热度

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