2012-04-18 32 views
0

我正试图编写简单的程序,在Linux中使用实时信号。但是,我遇到了奇怪的现象,首先代码:Linux和实时信号

#include<signal.h> 
#include<sys/types.h> 
#include<stdlib.h> 
#include<stdio.h> 
#include"errhandling.h" 
#include<string.h> 
#include<errno.h> 
#include<unistd.h> 

void baz(int sig,siginfo_t* info,void *context) 
{ 
    if (sig==SIGUSR1) 
     printf("SIGUSR1 %d\n",info->si_value.sival_int); 
    else if(sig==SIGRTMIN) 
     printf("SIGRTMIN %d\n",info->si_value.sival_int); 
    else 
     printf("SIGRTMIN+1 %d\n",info->si_value.sival_int); 
    return ; 
} 

void sig_output() 
{ 
    sigset_t set; 
    sigprocmask(0,NULL,&set); 
    printf("blokowane sa: "); 
    if (sigismember(&set,SIGUSR1)) 
     printf("SIGUSR1 "); 
    if(sigismember(&set,SIGUSR2)) 
     printf(" SIGUSR2"); 
    printf("\n"); 
    return ; 
} 


int received=0; 
int usr2=0; 

void foo(int sig) 
{ 
    return ; 
} 

void usr1_handler(int sig) 
{ 
    printf("usr1_handler\n"); 
    //++received; 
} 



void usr2_handler(int sig) 
{ 
    usr2=1; 
} 

int main(int argc,char **argv) 
{ 
    int i=0; 
    pid_t pid=getppid(); 
    struct sigaction a; 
    struct sigaction a2; 
    a.sa_flags=SA_SIGINFO; 
    sigset_t set; 
    sigemptyset(&set); 
    //sigaddset(&set,SIGRTMAX); 
    sigemptyset(&(a.sa_mask)); 
    sigemptyset(&(a2.sa_mask)); 
    a.sa_sigaction=baz; 
    sigaction(SIGRTMIN,&a,NULL); 
    a2.sa_handler=usr1_handler; 
    sigaction(SIGRTMIN+1,&a2,NULL); 
    //sigprocmask(SIG_SET,&(a.sa_mask),NULL); 
    while(!usr2) 
    { 
     printf("while\n"); 
     sigsuspend(&set); 

    } 
     //pause() 
    printf("after while\n"); 
    return EXIT_SUCCESS; 
} 

当我运行这个程序,它进入这个循环与sigsuspend我送这个节目SIGRTMIN一切正常的话 - 处理程序执行,并等待另一个信号,但当我发送SIGRTMIN + 1时,出现分段错误。

看来,实时信号我需要使用这个扩展的处理程序与3个参数,但为什么?它在某处指定了吗?我在我的朋友OpenSUSE 12.1上运行这个程序,并且我没有为SIGRTMIN + 1得到分段错误,但是在我的Xubuntu 11.10上,当我发送SIGRTMIN + 1时,出现分段错误。我的系统有问题吗?还是它依赖于实现?

+3

第1课:在信号处理程序不使用printf()函数。 – wildplasser 2012-04-18 12:19:04

+0

我知道这一点 - 这只是出于沮丧,因为我想获得一些信息 - 如果他进入我的信号处理程序。 – Andna 2012-04-18 12:21:11

+0

用vsnprintf()把它替换成本地缓冲区和write(),你可能就没事了。 – wildplasser 2012-04-18 12:22:35

回答

2

看来你缺少一个处理程序分配给a2.sa_sigaction


一般来说,是不是由原始的整数值是指信号,作为定义的各种信号可能是特定于平台的好主意。


Update:确保struct sigaction结构由例如memset()荷兰国际集团他们正确初始化为0。

+0

你是对的 - 它在复制代码期间失踪了,我改变了第一篇文章,我仍然得到SIGRTMIN + 1 – Andna 2012-04-18 12:25:52

1

不要使用printf()和朋友在信号处理中。不要固执......这是一个替代品。

#include <stdarg.h> 

int myprintf(const char *fmt, ...); 
int myprintf(const char *fmt, ...) 
{ 
    va_list args; 
    char buff[512]; 
    int rc; 

    va_start(args, fmt); 

    rc = vsnprintf (buff, sizeof buff, fmt, args); 
    va_end (args); 

    if (rc >0 && rc < sizeof buff) write(1, buff, rc); 

    return rc; 
} 

UPDATE:这似乎工作:

#include <signal.h> 
#include <sys/types.h> 
#include <stdlib.h> 
#include <stdio.h> 
#pragma #include"errhandling.h" 
#include <string.h> 
#include <errno.h> 
#include <unistd.h> 
#include <stdarg.h> 

int myprintf(const char *fmt, ...); 
int myprintf(const char *fmt, ...) 
{ 
    va_list args; 
    char buff[512]; 
    int rc; 

    va_start(args, fmt); 
    rc = vsnprintf (buff, sizeof buff, fmt, args); 
    va_end (args); 

    if (rc > 0 && rc < sizeof buff) write(1, buff, rc); 

    return rc; 
} 

void baz(int sig, siginfo_t *info, void *context) 
{ 
#define INFO_VAL(p) p?p->si_value.sival_int:0 
    if (sig==SIGUSR1) 
     myprintf("SIGUSR1 %d\n", INFO_VAL(info)); 
    else if(sig==SIGRTMIN) 
     myprintf("SIGRTMIN %d\n", INFO_VAL(info)); 
    else 
     myprintf("SIGRTMIN%+d %p\n", sig-SIGRTMIN, INFO_VAL(info)); 
    return ; 
#undef INFO_VAL 
} 

void sig_output() 
{ 
    sigset_t set; 
    sigprocmask(0,NULL,&set); 
    myprintf("blokowane sa: "); 
    if (sigismember(&set,SIGUSR1)) 
     myprintf("SIGUSR1 "); 
    if(sigismember(&set,SIGUSR2)) 
     myprintf(" SIGUSR2"); 
    myprintf("\n"); 
    return ; 
} 
volatile int received=0; 
volatile int usr2=0; 

void foo(int sig) 
{ 
    return ; 
} 

void usr1_handler(int sig) 
{ 
    myprintf("usr1_handler\n"); 
    //++received; 
} 



void usr2_handler(int sig) 
{ 
    usr2=1; 
} 

int main(int argc,char **argv) 
{ 
    int i=0; 
    pid_t pid=getppid(); 
    struct sigaction a, a2; 
    sigset_t set; 

    sigemptyset(&set); 
    //sigaddset(&set,SIGRTMAX); 
    sigemptyset(&a.sa_mask); 
    sigemptyset(&a2.sa_mask); 
    a.sa_flags = 0; 
    a2.sa_flags = SA_SIGINFO; 
    a2.sa_sigaction = baz; 
    a.sa_handler = usr1_handler; 
    sigaction(SIGUSR1,&a,NULL); 

    a.sa_handler = usr2_handler; 
    sigaction(SIGUSR2,&a,NULL); 

    sigaction(SIGRTMIN+1,&a2,NULL); 
    sigaction(SIGRTMIN+2,&a2,NULL); 
    sigaction(SIGRTMIN+3,&a2,NULL); 
    //sigprocmask(SIG_SET,&(a.sa_mask),NULL); 
    while(!usr2) 
    { 
     myprintf("while(!usr2)\n"); 
     sigsuspend(&set); 

    } 
     //pause() 
    myprintf("after while\n"); 
    return EXIT_SUCCESS; 
} 
+0

的段错误我敢打赌这个'a.sa_flags = 0;'完成了这项工作。 – alk 2012-04-18 14:31:48

+0

是的,metoo。我在你的回答中看到了,而我已经把它放到了我的本地副本中。 (a和a2的处理在很多地方有所不同) – wildplasser 2012-04-18 14:39:59

+0

这没有帮助。 'snprintf'没有被指定为异步信号安全的,并且在现实世界中(例如glibc),它是非常异步信号不安全的(它甚至称为“malloc”)。理想情况下'snprintf' *应该被指定为异步信号安全的,但是让每个人修复其不好的实现并不是一件容易的事情... – 2012-04-18 14:40:00