为什么Python';s Event.wait()是否会被某些系统上的信号而不是其他系统上的信号中断?
考虑以下Python脚本:为什么Python';s Event.wait()是否会被某些系统上的信号而不是其他系统上的信号中断?,python,signals,Python,Signals,考虑以下Python脚本: from datetime import datetime from threading import Event event = Event() start = datetime.now() try: event.wait(5) except KeyboardInterrupt: print("caught Ctrl+C after %s" % (datetime.now() - start)) 当我在Debian上运行它(特别是Docker的
from datetime import datetime
from threading import Event
event = Event()
start = datetime.now()
try:
event.wait(5)
except KeyboardInterrupt:
print("caught Ctrl+C after %s" % (datetime.now() - start))
当我在Debian上运行它(特别是Docker的python:3.6.5-stretch)并快速按下Ctrl+C时,它会立即中断:
# python mptest.py
^Ccaught Ctrl+C after 0:00:00.684854
#
但当我在Alpine上运行它(具体来说,Docker的python:3.6.5-alpine3.7)并快速按下Ctrl+C时,整个等待过程就会结束:
/ # python mptest.py
^Ccaught Ctrl+C after 0:00:05.000314
/ #
造成这种差异的原因是什么?其中一个系统不正确吗?短版本: Python假设如果信号在等待时中断,
sem\u timedwait
将返回EINTR
。Glibc(Debian的libc)做到了这一点,但POSIX说这样做是可选的,而musl(Alpine的libc)则没有做到
长版本:
Python的事件
是内部的,它本身就是。以下程序出于相同的原因显示了相同的行为,仅使用了锁
:
from datetime import datetime
from threading import Lock
lock = Lock()
lock.acquire()
start = datetime.now()
try:
lock.acquire(True, 5)
except KeyboardInterrupt:
print("caught Ctrl+C after %s" % (datetime.now() - start))
发件人:
锁获取现在可以被POSIX上的信号中断
假设这段文档是正确的,这意味着Debian上的行为是正确的,而Alpine上的行为是不正确的
Python的acquire
是(假设它存在,它在Debian和Alpine上都存在。如果它不存在,它就会存在)
以下C程序演示了在每个系统上构建时,sem_timedwait
的不一致性:
#包括
#包括
#包括
#包括
#包括
#包括
#包括
无效处理程序(int sig){
放入(“信号处理器”);
}
int main(){
struct-sigaction-sa;
sa.sa_handler=handler;
sigemptyset(和sa.sa_面具);
sa.sa_标志=0;
sigaction(SIGALRM,&sa,NULL);
警报(1);
结构timespects;
时钟获取时间(时钟实时,&ts);
ts.tv_sec+=2;
扫描电镜;
sem_init(&sem,0,0);
sem_timedwait(&sem,&ts);
如果(errno==EINTR){
puts(“被信号中断”);
}else if(errno==ETIMEDOUT){
卖出(“超时”);
}
返回0;
}
在Debian上,它在1秒后以“被信号中断”退出。在阿尔卑斯山,它在2秒后退出,并显示“超时”
sem_timedwait
是一个libc函数。特别是,它声明它“可能”因EINTR而失败,而不是“应该”。这意味着glibc(Debian's)和musl(Alpine's)都不正确
对,穆尔
在我看来,这里的错误在于Python依赖POSIX的可选特性。事实证明,Python以前曾被攻击过,因为信号量不存在,它使用了pthread\u cond\u timedwait
。此外,此问题还会导致在针对musl构建时失败。我打开了这个