Signal Raised事件在Linux中停止我的复制过程

时间:2012-05-22 09:24:03

标签: c linux signals

这里我有一个信号处理和复制过程的示例代码。 在这里,我想每秒使用信号动作调用一个计时器。 它的工作正常,但是当我在启动和停止计时器功能之间添加我的复制过程代码时,我的复制过程将在第一次发出信号时被杀死,这意味着在1秒之后。

这里我尝试了这些SIGRTMAX ,SIGUSR1, SIGALRM信号,但它们都给出了相同的结果。

为什么我的复制过程会在发出信号时停止。?

代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h>
#include <sys/time.h>
#include <unistd.h>

#define SIGTIMER SIGRTMAX


timer_t KeepAliveTimerId;



void stopKeepAlive()
{
    if(KeepAliveTimerId != NULL)
    {
        timer_delete(KeepAliveTimerId);
        printf("timer delete\n");

    }
}

void  signalHandler(int signo, siginfo_t* info, void* context)
{
    if (signo == SIGTIMER)
    {
        printf("Signal Raised\n");
    }
}

int startKeepAlive()
{
    struct sigevent sigev; //signal event struct
    struct itimerspec itval;
    struct itimerspec oitval;
    struct sigaction sigact;


    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = SA_SIGINFO;
    sigact.sa_sigaction = signalHandler;

    // set up sigaction to catch signal
    if (sigaction(SIGTIMER, &sigact, NULL) == -1)
    {
        printf("time_settime error \n");
        return -1;
    }

    //Create the POSIX timer to generate signo
    sigev.sigev_notify = SIGEV_SIGNAL;
    sigev.sigev_signo = SIGTIMER;
    sigev.sigev_value.sival_int = 2;

    if (timer_create(CLOCK_REALTIME, &sigev, &KeepAliveTimerId) == 0)
     {
        itval.it_value.tv_sec = 1;
        itval.it_value.tv_nsec = 0L;
        itval.it_interval.tv_sec = itval.it_value.tv_sec;
        itval.it_interval.tv_nsec = itval.it_value.tv_nsec;

        if (timer_settime(KeepAliveTimerId, 0, &itval, &oitval) != 0)
        {
            printf("Error in set time \n");
            return -2;
        }
    }
    else
    {
        printf("Error in creating timer \n");
        return -3;
    }
    return 0;
}


int main()
{
    int result; 
    // Start Timer
    startKeepAlive();

    result = system("cp /mnt/bct/package.QuipC /Download/ 2>&1");
    if (result == 0)
    {
        printf("result is %d\n",result);
        //stop timer
        stopKeepAlive();
        return EXIT_SUCCESS;
    }
    printf("result is %d\n",result);
    // Stop Timer
    stopKeepAlive();
   return EXIT_FAILURE;
}

3 个答案:

答案 0 :(得分:0)

您使用来自http://www.kernel.org/doc/man-pages/online/pages/man7/signal.7.html的实时信号:

  

...   未处理的实时信号的默认操作是终止   接收过程......

所以看来调用system(...)会以某种方式影响你的信号处理程序。我建议(如已经提到的wildplasser)摆脱明显的错误(信号处理程序中的printf)。在上面的链接中,你还有很好的函数列表,可以在信号处理程序中使用(段落异步信号安全函数)。在你这样做之后,请告诉我们它是否有任何不同。

答案 1 :(得分:0)

为了确保我添加了这个:

#include <stdarg.h>
int zprintf(char *fmt, ...);
int zprintf(char *fmt, ...)
{
int rc;
char buff[100];
va_list aaa;

va_start(aaa, fmt);
rc = sprintf(buff, fmt, aaa);
va_end(aaa);

rc = write(2, buff, rc);
return rc;
}

并将信号处理程序替换为:

void  signalHandler(int signo, siginfo_t* info, void* context)
{
    if (signo == SIGTIMER)
    {
        zprintf("Signal Raised\n");
    }
    else
    {
        zprintf("Signal %d Raised\n", signo);
    }
}

...并替换了system()字符串,如:

result = system("cp ../wakker/megahal-9.1.1.dld/tele/megahal.brn /tmp/ 2>&1");

它有效:

$ ./a.out
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
result is 0
timer delete
可能是巧合。 (但未定义的行为也是巧合!)

答案 2 :(得分:0)

我编译了这段代码(原始的微不足道的变体 - 添加了明确的void参数列表,#define _XOPEN_SOURCE 700来获取timer_t声明,简化了信号处理程序,并链接和测试了带有-lrt的Linux(RHEL 5),因为Mac OS X在timer_t下的任何标头中没有/usr/include - 执行更简单的命令(echo,sleep,echo),并获得看似合理的产出:

Started
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Done
result is 0
timer delete

我从中推断出,时间信号不会影响system()运行的命令,实际上它们不应该。{/ p>

gcc -Wall -Wextra -g -O3 -std=c99 sau.c -o sau -lrt

-std=c99选项可能是我需要指定_XOPEN_SOURCE的原因。如果我可能不愿意使用-std=gnu99进行编译,则可能不需要它。

代码

#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h>
#include <sys/time.h>
#include <unistd.h>

#define SIGTIMER SIGRTMAX

timer_t KeepAliveTimerId;

void stopKeepAlive(void)
{
    if(KeepAliveTimerId != NULL)
    {
        timer_delete(KeepAliveTimerId);
        printf("timer delete\n");
    }
}

void  signalHandler(int signo)
{
    if (signo == SIGTIMER)
    {
        printf("Signal Raised\n");
    }
}

int startKeepAlive(void)
{
    struct sigevent sigev; //signal event struct
    struct itimerspec itval;
    struct itimerspec oitval;
    struct sigaction sigact;

    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigact.sa_handler = signalHandler;

    // set up sigaction to catch signal
    if (sigaction(SIGTIMER, &sigact, NULL) == -1)
    {
        printf("time_settime error \n");
        return -1;
    }

    //Create the POSIX timer to generate signo
    sigev.sigev_notify = SIGEV_SIGNAL;
    sigev.sigev_signo = SIGTIMER;
    sigev.sigev_value.sival_int = 2;

    if (timer_create(CLOCK_REALTIME, &sigev, &KeepAliveTimerId) == 0)
     {
        itval.it_value.tv_sec = 1;
        itval.it_value.tv_nsec = 0L;
        itval.it_interval.tv_sec = itval.it_value.tv_sec;
        itval.it_interval.tv_nsec = itval.it_value.tv_nsec;

        if (timer_settime(KeepAliveTimerId, 0, &itval, &oitval) != 0)
        {
            printf("Error in set time \n");
            return -2;
        }
    }
    else
    {
        printf("Error in creating timer \n");
        return -3;
    }
    return 0;
}

int main(void)
{
    int result; 
    // Start Timer
    startKeepAlive();

    result = system("echo Started; sleep 10; echo Done");
    if (result == 0)
    {
        printf("result is %d\n",result);
        //stop timer
        stopKeepAlive();
        return EXIT_SUCCESS;
    }
    printf("result is %d\n",result);
    // Stop Timer
    stopKeepAlive();
   return EXIT_FAILURE;
}