我编写了一个代码,我从父线程创建了两个子线程。
然后,当从那些子线程内的另一个终端接收到信号时,我打印了threadID
并退出了线程。
我有两个问题。
我收到来自子线程的信号。为什么要打印父线程的threadID
?
杀死父线程后,子线程如何活着?
守则:
void sig_handler(int signo)
{
if (signo == 1){
printf("%d\n", pthread_self());
pthread_exit(NULL);
}
}
void* doSomeThing(void* arg)
{
printf("In function -> %d\n", pthread_self());
if (signal(1, sig_handler) == SIG_ERR)
printf("\ncan't catch SIGHUP\n");
while(1)
sleep(1);
return NULL;
}
int main(int argc, char *argv[])
{
printf("In function -> %d\n", pthread_self());
char *ch1;
pthread_t tid1, tid2;
ch1 = "random";
int ret1, ret2;
ret1 = pthread_create(&tid1, NULL, &doSomeThing, (void *) ch1 );
ret2 = pthread_create(&tid2, NULL, &doSomeThing, (void *) ch1 );
while(1)
sleep(1);
return 0;
}
这是终端中给出的输出图像:
前3行是3 threadID
。第一个是主threadID
,然后是两个辅助线程。
然后从以下代码块打印threadID
。
if (signo == 1){
printf("%d\n", pthread_self());
pthread_exit(NULL);
}
为什么会发生这种情况?
答案 0 :(得分:3)
信号将传递到进程,而不是传递给单个线程。所以,你不能只为一个线程拥有一个信号处理程序,就像你在这里做的那样。
您可以做的是使用pthread_sigmask()
阻止您感兴趣的信号,并让专用线程使用sigwait()
处理信号,这是最常用的方式。
答案 1 :(得分:0)
此外,您只能从信号处理程序中安全地调用异步信号安全函数。来自https://msdn.microsoft.com/en-us/library/system.data.datarow.isnull.aspx:
异步信号安全功能
自处理以来,信号处理函数必须非常小心 其他地方可能会在执行中的某个任意点中断 该计划。 POSIX具有“安全功能”的概念。如果一个 signal中断执行不安全的函数,以及 handler 要么调用不安全的函数,要么处理程序通过调用终止
siglongjmp()
或printf()
,程序随后调用 不安全的函数,那么程序的行为是不确定的。
链接的手册页有一个可以安全地从信号处理程序中调用的函数列表。如果该功能不在该列表中,则称其不安全。没有例外。
请注意,pthread_exit()
和pthread_exit()
都不在异步信号安全功能列表中。
从信号处理程序中调用$fields_string = '';
$fields = array(
'v' => 1,
'tid' => "UA-xxxxxx-1",
'cid' => $userid,
't' => 'transaction',
'ti' => $transaction_id,
'tr' => $Transaction_revenue,
'ts' => $Transaction_shipping,
'tt' => $tax,
'cu' =>'EUR'
);
会产生其他几个问题:
退出的主题通常不受任何控制。在许多情况下,信号可以传递给任何线程。
退出线程可以使对象处于未知状态 - 例如,互斥锁可以被不再存在的线程锁定。
还将从信号处理程序上下文中调用任何线程清理处理程序the Linux signal
man page。