我想忽略线程生命周期的前100秒的信号,我开发了这个解决方案,但它不起作用,我缺少了什么部分?
问题陈述: 编写一个包含两个线程的程序 - 创建线程(线程A)和创建线程(线程B)。在创建线程B之后,线程A等待线程B终止然后它自己终止。线程B仅在稍后描述的特殊情况下终止。信号SIGINT(ctrl C)在线程B中被阻塞(即,只有线程A处理SIGINT)。每次,用户按下ctrl C,线程A尝试取消线程B.线程B保持等待在其生命的前100秒内收到的任何取消请求。一旦线程B的生命的前100秒结束,任何取消请求都将被尊重。此外,线程B以每10秒后的秒数打印其当前生命周期。
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
void function_to_time(void);
static void *thread_func(void *arg)
{
struct sigaction act;
sigaction(SIGINT,NULL,&act);
act.sa_handler = SIG_IGN;
sigaction(SIGINT,&act,NULL);
sigset_t sigmask;
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGALRM);
sigprocmask(SIG_BLOCK,&sigmask,NULL);
sigemptyset(&sigmask);
sigaddset(&sigmask,SIGALRM);
sigaddset(&sigmask,SIGINT);
alarm(100);
int sigintsReceived = 0;
int sigalrmsReceived = 0;
while( 1 == 1)
{
int recvdSig;
sigwait(&sigmask,&recvdSig);
if( recvdSig == SIGALRM )
{
if( sigalrmsReceived == 0 )
{
sigalrmsReceived++;
printf("\npthread_cancel is enabled\n");
sigset_t sigmask2;
sigemptyset(&sigmask2);
sigaddset(&sigmask2, SIGINT);
sigprocmask(SIG_BLOCK,&sigmask2,NULL);
sigaction(SIGINT,NULL,&act);
act.sa_handler = SIG_DFL;
sigaction(SIGINT,&act,NULL);
}
}
};
return 0;
}
int main(void)
{
sigset_t set;
pthread_t thr;
void *res;
int s;
s = pthread_create(&thr, NULL, &thread_func, (void *)&set);
if (s != 0)
handle_error_en(s, "pthread_create");
sigemptyset(&set);
sigaddset(&set, SIGINT);
pthread_sigmask(SIG_BLOCK, &set, NULL);
int recvdSig;
sigwait(&set,&recvdSig);
if( recvdSig == SIGINT )
{
printf("Signal received\n");
printf("main(): sending cancellation request\n");
s = pthread_cancel(thr);
if (s != 0)
handle_error_en(s, "pthread_cancel");
}
s = pthread_join(thr, &res);
if (s != 0)
handle_error_en(s, "pthread_join");
if (res == PTHREAD_CANCELED)
printf("main(): thread was canceled\n");
else
printf("main(): thread wasn't canceled (shouldn't happen!)\n");
exit(EXIT_SUCCESS);
}
答案 0 :(得分:0)
仔细阅读signal(7)&amp; signal-safety(7)。您只能在信号处理程序中使用(直接和间接) async-signal-safe 函数。请注意errno(3)中的EINTR
并在每次阻止系统调用后对其进行测试(例如,在read(2)或 stdio 之后)。
信号和pthreads(7)无法很好地协同工作。信号处理适用于整个过程(不适用于其中的单个线程)。
您可以使用sigprocmask(2),更好的是pthread_sigprocmask(3)。
一个常见的技巧是在初始化时将pipe(7)设置为self,在信号处理程序中设置write(2)一个或几个字节,然后poll(2)然后设置read(2)。在Qt文档中,这个技巧是explained。
使用调试器gdb
和strace(1)调试您的程序。
答案 1 :(得分:0)
编写一个有两个线程的程序 - 创建线程(线程A)和 创建线程(线程B)。在创建线程B之后,线程A等待 线程B终止然后终止自身。线程B. 仅在稍后描述的特殊情况下终止。信号 SIGINT(ctrl C)在线程B中被阻止(即只有线程A处理 SIGINT)。每次,用户按下ctrl C,线程A尝试取消 线程B.线程B保持等待收到的任何取消请求 在其生命的前100秒。任何取消请求是 在线程B的生命结束的第一个100秒之后,我很荣幸。 此外,线程B以秒为单位打印其当前生命周期 每10秒钟一次。
如果我理解得很好,你可以试试:
线程B可以屏蔽SIGUSR1和SIGINT(alarm
),设置10秒的警报(start
)及其打印当前时间的处理程序,计算这些中断的数量,当达到10时,取消屏蔽SIGUSR1。
线程A可以屏蔽SIGUSR1和SIGALRM并捕获SIGINT,当收到SIGINT时,它将在加入线程B时提供所有这一切的SIGUSR1。
在这种情况下,SIGUSR1用作&#34;取消&#34;对于线程B。