C 次线程中的信号处理
我正在编写一个程序来演示辅助线程中的信号处理。在我的程序中,主线程生成10个线程,每个线程调用C 次线程中的信号处理,c,linux,macos,signals,C,Linux,Macos,Signals,我正在编写一个程序来演示辅助线程中的信号处理。在我的程序中,主线程生成10个线程,每个线程调用sigwait等待信号。但在我的例子中,处理signa的是主线程。代码如下: #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/syscall.h> #include <unistd.h> #
sigwait
等待信号。但在我的例子中,处理signa的是主线程。代码如下:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <errno.h>
volatile sig_atomic_t cont = 1;
volatile sig_atomic_t wsig = 0;
volatile sig_atomic_t wtid = 0;
int GetCurrentThreadId()
{
return syscall(__NR_gettid);
}
void Segv1(int, siginfo_t *, void *)
{
//printf("SIGSEGV signal on illegal memory access handled by thread: %d\n", GetCurrentThreadId());
wtid = GetCurrentThreadId();
wsig = SIGSEGV;
_exit(SIGSEGV);
}
void Fpe1(int , siginfo_t *, void *)
{
wtid = GetCurrentThreadId();
wsig = SIGFPE;
_exit(SIGFPE);
}
void User1(int, siginfo_t *, void *)
{
wtid = GetCurrentThreadId();
wsig = SIGUSR1;
}
void* ThreadFunc (void*)
{
sigset_t sigs;
sigemptyset(&sigs);
sigaddset(&sigs, SIGUSR1);
sigaddset(&sigs, SIGSEGV);
sigaddset(&sigs, SIGFPE);
pthread_sigmask(SIG_BLOCK, &sigs, NULL);
//printf("Thread: %d starts\n", GetCurrentThreadId());
while(cont) {
//printf("Thread: %d enters into loop\n", GetCurrentThreadId());
//int s = sigwaitinfo(&sigs, NULL);
//int sig;
//int s = sigwait(&sigs, &sig);
//printf("A signal\n");
/*if(s==0) {
sigaddset(&sigs, sig);
printf("Signal %d handled from thread: %d\n", sig, GetCurrentThreadId());
if(sig==SIGFPE||sig==SIGSEGV)
return NULL;
} else {
printf("sigwaitinfo failed with %d\n", s);
break;
}*/
int s = sigsuspend(&sigs);
switch(wsig) {
case SIGSEGV:
printf("Segmenation fault in thread: %d Current thread id: %d\n", wtid, GetCurrentThreadId());
exit(1);
break;
case SIGFPE:
printf("Floating point exception in thread: %d Current thread id: %d\n", wtid, GetCurrentThreadId());
exit(1);
break;
case SIGUSR1:
printf("User 1 signal in thread: %d Current thread id: %d\n", wtid, GetCurrentThreadId());
break;
default:
printf("Unhandled signal: %d in thread: %d Current thread id: %d\n", wsig, wtid, GetCurrentThreadId());
break;
}
}
printf("Thread: %d ends\n", GetCurrentThreadId());
return NULL;
}
int main()
{
printf("My PID: %d\n", getpid());
printf("SIGSEGV: %d\nSIGFPE: %d\nSIGUSR1: %d\n", SIGSEGV, SIGFPE, SIGUSR1);
//Create a thread for signal
struct sigaction act;
memset(&act, 0, sizeof act);
act.sa_sigaction = User1;
act.sa_flags = SA_SIGINFO;
//Set Handler for SIGUSR1 signal.
if(sigaction(SIGUSR1, &act, NULL)<0) {
fprintf(stderr, "sigaction failed\n");
return 1;
}
//Set handler for SIGSEGV signal.
act.sa_sigaction = Segv1;
sigaction(SIGSEGV, &act, NULL);
//Set handler for SIGFPE (floating point exception) signal.
act.sa_sigaction = Fpe1;
sigaction(SIGFPE, &act, NULL);
sigset_t sset;
sigemptyset(&sset);
sigaddset(&sset, SIGUSR1);
sigaddset(&sset, SIGSEGV);
sigaddset(&sset, SIGFPE);
//pthread_sigmask(SIG_BLOCK, &sset, NULL);
const int numthreads = 10;
pthread_t tid[numthreads];
for(int i=0;i<numthreads;++i)
pthread_create(&tid[i], NULL, ThreadFunc, NULL);
sleep(numthreads/2);
int sleepval = 15;
int pid = fork();
if(pid) {
while(sleepval) {
sleepval = sleep(sleepval);
//It might get interrupted with signal.
switch(wsig) {
case SIGSEGV:
printf("Segmenation fault in thread: %d\n", wtid);
exit(1);
break;
case SIGFPE:
printf("Floating point exception in thread: %d\n", wtid);
exit(1);
break;
case SIGUSR1:
printf("User 1 signal in thread: %d\n", wtid);
break;
default:
printf("Unhandled signal: %d in thread: %d\n", wsig, wtid);
break;
}
}
} else {
for(int i=0;i<10;++i) {
kill(getppid(), SIGUSR1);
//If sleep is not used, signal SIGUSR1 will be handled one time in parent
//as other signals will be ignored while SIGUSR1 is being handled.
sleep(1);
}
return 0;
}
int * a = 0;
//*a = 1;
int c=0;
//c = 0;
int b = 1/c; //send SIGFPE signal.
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
挥发性sig_原子含量=1;
挥发性sig_原子wsig=0;
挥发性sig_原子wtid=0;
int GetCurrentThreadId()
{
返回系统调用(_NR_getId);
}
void Segv1(int,siginfo\u t*,void*)
{
//printf(“线程处理的非法内存访问的SIGSEGV信号:%d\n”,GetCurrentThreadId());
wtid=GetCurrentThreadId();
wsig=SIGSEGV;
_出口(SIGSEGV);
}
无效Fpe1(int,siginfo\u t*,void*)
{
wtid=GetCurrentThreadId();
wsig=SIGFPE;
_出口(SIGFPE);
}
void User1(int,siginfo\u t*,void*)
{
wtid=GetCurrentThreadId();
wsig=SIGUSR1;
}
void*ThreadFunc(void*)
{
sigset_t sigs;
sigp&sigs;
sigaddset(&sigs,SIGUSR1);
sigaddset(&sigs,SIGSEGV);
sigaddset(&sigs,SIGFPE);
pthread_sigmask(SIG_块和sigs,NULL);
//printf(“线程:%d开始\n”,GetCurrentThreadId());
while(续){
//printf(“线程:%d进入循环\n”,GetCurrentThreadId());
//int s=sigwaitinfo(&sigs,NULL);
//int-sig;
//int s=sigwait(&sigs,&sig);
//printf(“信号”);
/*如果(s==0){
sigaddset(&sigs,sig);
printf(“从线程%d处理的信号%d\n”,sig,GetCurrentThreadId());
if(sig==SIGFPE | | sig==SIGSEGV)
返回NULL;
}否则{
printf(“sigwaitinfo失败,出现%d\n”,s);
打破
}*/
int s=sigsupspend(&sigs);
开关(wsig){
案例SIGSEGV:
printf(“线程中的分段错误:%d当前线程id:%d\n”,wtid,GetCurrentThreadId());
出口(1);
打破
案例SIGFPE:
printf(“线程中的浮点异常:%d当前线程id:%d\n”,wtid,GetCurrentThreadId());
出口(1);
打破
案例SIGUSR1:
printf(“线程中的用户1信号:%d当前线程id:%d\n”,wtid,GetCurrentThreadId());
打破
违约:
printf(“线程中未处理的信号:%d:%d当前线程id:%d\n”,wsig,wtid,GetCurrentThreadId());
打破
}
}
printf(“线程:%d结束\n”,GetCurrentThreadId());
返回NULL;
}
int main()
{
printf(“我的PID:%d\n”,getpid());
printf(“SIGSEGV:%d\nSIGFPE:%d\nSIGUSR1:%d\n”,SIGSEGV,SIGFPE,SIGUSR1);
//为信号创建一个线程
结构动作法;
memset(&act,0,sizeof act);
act.sa_sigaction=User1;
act.sa_flags=sa_SIGINFO;
//设置SIGUSR1信号的处理程序。
如果(sigaction(SIGUSR1,&act,NULL)我建议您应该在主线程中SIG_阻塞所需的信号(现在注释掉),并在其他线程中解除SIG_阻塞(现在SIG_阻塞)。或者您可以在主线程中生成您的线程,然后在主线程中生成SIG_阻塞,因为生成的线程从父线程获得了sigmask。
SIGSSUSPEND的参数不是你想唤醒的信号,反之亦然。我建议你应该在主线程中屏蔽所需的信号(现在注释掉),然后在其他线程中解除屏蔽(现在屏蔽)。或者你可以在主线程中生成你的线程,然后屏蔽,因为生成的线程从父线程获得了sigmask。
SIGSSUSPEND的参数不是您想要唤醒的信号,反之亦然
在Linux和Mac OS X上,是否有任何选择线程进行信号处理的规则
有,请参阅:
在信号生成与传递或接受之间的时间段内,信号被称为挂起。通常,应用程序无法检测到该间隔。但是,可以阻止信号传递到线程。如果与被阻止信号相关联的操作不是忽略该信号,而是为线程生成ignal时,该信号应保持挂起状态,直到解除阻止为止。当选择该信号并通过调用sigwait()返回时,该信号将被接受函数,或与之相关的操作设置为忽略信号。为进程生成的信号应恰好传递给进程中正在调用sigwait()函数的线程中的一个,该函数选择该信号或未阻止信号的传递。如果调用sigwait()中没有线程函数选择该信号,如果进程中的所有线程都阻止了信号的传递,则该信号应在进程上保持挂起状态,直到线程调用sigwait()为止函数选择该信号时,线程会解锁该信号的传递,或者将与该信号相关的操作设置为忽略该信号。如果与被阻止的信号相关的操作将忽略该信号,并且如果该信号是为进程生成的,则未指定是在生成后立即丢弃该信号还是rem悬而未决
在Linux和Mac OS X上,是否有任何选择线程进行信号处理的规则
有,请参阅:
在信号生成与传递或接受之间的时间段内,信号被称为挂起。通常,应用程序无法检测到该间隔。但是,可以阻止信号传递到线程。如果与被阻止信号相关联的操作不是忽略该信号,而是为线程生成信号时,该信号应保持挂起状态,直到其被解除阻止,当它被选中并通过调用sigwait()函数返回时被接受,或者与之相关的操作被设置为忽略该信号。为进程生成的信号应在