Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 次线程中的信号处理_C_Linux_Macos_Signals - Fatal编程技术网

C 次线程中的信号处理

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> #

我正在编写一个程序来演示辅助线程中的信号处理。在我的程序中,主线程生成10个线程,每个线程调用
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()函数返回时被接受,或者与之相关的操作被设置为忽略该信号。为进程生成的信号应在