是否有方法等待线程终止,但仍截获信号?
考虑以下C程序:
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
void* server_thread(void* dummy) {
sleep(10);
printf("Served\n");
return NULL;
}
void* kill_thread(void* dummy) {
sleep(1); // Let the main thread join
printf("Killing\n");
kill(getpid(), SIGUSR1);
return NULL;
}
void handler(int signum) {
printf("Handling %d\n", signum);
exit(42);
}
int main() {
pthread_t servth;
pthread_t killth;
signal(SIGUSR1, handler);
pthread_create(&servth, NULL, server_thread, NULL);
pthread_create(&killth, NULL, kill_thread, NULL);
pthread_join(servth, NULL);
printf("Main thread finished\n");
return 0;
}
一秒钟后结束打印:
Killing
Handling 10
相比之下,我尝试用Python编写它:
#!/usr/bin/env python
import signal, time, threading, os, sys
def handler(signum, frame):
print("Handling " + str(signum) + ", frame:" + str(frame))
exit(42)
signal.signal(signal.SIGUSR1, handler)
def server_thread():
time.sleep(10)
print("Served")
servth = threading.Thread(target=server_thread)
servth.start()
def kill_thread():
time.sleep(1) # Let the main thread join
print("Killing")
os.kill(os.getpid(), signal.SIGUSR1)
killth = threading.Thread(target=kill_thread)
killth.start()
servth.join()
print("Main thread finished")
它打印:
Killing
Served
Handling 10, frame:<frame object at 0x12649c0>
我该如何让它表现得像C版本?
在调用
join
之前对isAlive
进行轮询。当然,这种轮询可以被中断,一旦线程没有isAlive
,就可以立即join
。另一种方法是使用超时在
join
上轮询,使用isAlive
检查是否发生超时。这会比以前的方法花费更少的CPU。考虑到全局解释器锁,Python中的线程有些奇怪。如果不按照eliben的建议使用连接超时和isAlive,您可能无法实现所需的功能。
文档中有两个地方给出了这种情况的原因(可能还有更多)。
第一个:
来自http://docs.python.org/library/signal.html#module-signal:
第二个,来自http://docs.python.org/library/thread.html#module-thread:
编辑:在python bug tracker上有一个关于这个机制的不错的讨论:http://bugs.python.org/issue1167930。当然,最后圭多说:“那不太可能消失,所以你只能活着 带着这个。正如您所发现的,指定超时可以解决问题 (差不多)
Jarret Hardie已经mentioned it:根据Guido van Rossum,目前没有更好的方法:如documentation,
join(None)
块中所述(这意味着没有信号)。另一种方法是用一个巨大的超时(join(2**31)
)调用并检查isAlive
看起来很棒。然而,Python处理计时器的方式是灾难性的,在使用servth.join(100)
而不是servth.join()
运行Python测试程序时可以看到:也就是说,Python每50毫秒唤醒一次,导致单个应用程序无法让CPU休眠。
相关问题 更多 >
编程相关推荐