2012-04-18 6 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, я получаю ошибку сегментации.

Кажется, что для сигналов в реальном времени мне нужно использовать этот расширенный обработчик с тремя аргументами, но почему? Он определен где-то? Я запускаю эту программу у своего друга OpenSUSE 12.1, и я не получаю ошибку сегментации для SIGRTMIN + 1, но на моем Xubuntu 11.10, когда я отправляю SIGRTMIN + 1, я получаю ошибку сегментации. Это проблема с моей системой? Или это зависит от реализации?

+3

Урок 1: не используйте Е() в обработчике сигнала. – wildplasser

+0

Я знаю об этом - это только из-за разочарования, потому что я хотел получить некоторую информацию - если он войдет в мои обработчики сигналов. – Andna

+0

Замените его на vsnprintf() в локальный буфер и write(), и вы, вероятно, будете в порядке. – wildplasser

ответ

2

Кажется, вам не хватает назначить обработчик a2.sa_sigaction.


В общем случае это не хорошая идея, чтобы обратиться к сигналам с помощью исходных целочисленных значений, в качестве определения для различных сигналов может быть конкретной платформы.


Update: Убедитесь struct sigaction структуры инициализируются должным образом, например, memset() ИНГ их в 0.

+0

Вы правы - он пропал во время копирования кода, я изменил первый пост, все же у меня возникла ошибка сегментации для SIGRTMIN + 1 – Andna

1

Не используйте Е() и друзей внутри обработчика сигнала. Не будь упрямым ... Вот замена.

#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

+0

Да, metoo. Я видел в вашем ответе, пока я уже вложил его в свою локальную копию нарушающей программы. (обработка a и a2 различалась в нескольких местах) – wildplasser

+0

Это не поможет. 'snprintf' не указывается как безопасный для асинхронного сигнала, так и в реальном мире (например, glibc) он очень несинхронизирован с сигналом-сигналом (он даже вызывает' malloc'). В идеале 'snprintf' * должен быть * указан как безопасный для асинхронного сигнала, но заставить всех исправить их плохие реализации - непростая задача ... –

Смежные вопросы