间隔太小时定时器解除

问题描述

仅当间隔太小时,计时器似乎在进程恢复(SIGCONT)后才解除。 我将 timer_create 与 CLOCK_REALTIME 一起使用。

我的 Linux 发行版是 ubuntu 20.04.1

这是显示问题的代码

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <stdlib.h>
#include <memory.h>

volatile siginfo_t sigInfo;

void childFunction();
void parentFunction(pid_t pid);
void ignoreChild();
void signalFunction(int signo,siginfo_t* SI,void* data);

int main(int argc,char* argv[])
{
    ignoreChild();
    pid_t pid;
    pid = fork();

    switch(pid)
    {
        case -1:
        {
            perror("Error in fork!\n");
            exit(EXIT_FAILURE);
        }
        case 0:
        {
            childFunction();
            exit(EXIT_SUCCESS);
        }
        default:
        {
            parentFunction(pid);
            break;
        }
    }

    return 0;
}

void signalFunction(int signo,void* data)
{
    sigInfo = *SI;
}

void parentFunction(pid_t pid)
{
    struct sigaction sa;
    struct timespec sleepTime = { .tv_sec = 1,.tv_nsec = 0};
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = signalFunction;
    if (sigaction(SIGCHLD,&sa,NULL) == -1)
    {
        perror("Error in sigaction!\n");
        exit(EXIT_FAILURE);
    }
    //---- for blocking
    sigset_t set = {0};
    if (sigaddset(&set,SIGCHLD) == -1)
    {
        perror("Error in sigaddset!\n");
        exit(EXIT_FAILURE);
    }
    while (1)
    {
        if (pause() == -1)
        {
            if (errno == EINTR)
            {
                if (sigprocmask(SIG_BLOCK,&set,NULL) == -1)
                {
                    perror("Error in sigprocmask!\n");
                    exit(EXIT_FAILURE);
                }

                if (sigInfo.si_status == SIGSTOP)
                {
                    printf("Child received SIG_STOP signal\n");
                    nanosleep(&sleepTime,NULL);
                    kill(pid,SIGCONT);
                }
                if (sigInfo.si_status == SIGCONT)
                {
                    printf("Child received SIGCONT signal!\n");
                }
                if (sigInfo.si_code == CLD_EXITED)
                {
                    printf("Child is dead!\n");
                    break;
                }
                if (sigprocmask(SIG_UNBLOCK,NULL) == -1)
                {
                    perror("Error in sigprocmask2!\n");
                    exit(EXIT_FAILURE);
                }
            }
        }
    }
}

void ignoreChild()
{
    struct sigaction sa;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_NOCLDWAIT;
    if (sigaction(SIGCHLD,NULL) == -1)
    {
        perror("Error in sigaction!\n");
        exit(EXIT_FAILURE);
    }
}

void childFunction()
{
    struct sigevent sev;
    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIGSTOP;
    struct timespec timeForTimer = { .tv_sec = 1,.tv_nsec = 0}; //     set time for timer here!
    struct itimerspec ts = { .it_interval = timeForTimer,.it_value = timeForTimer };
    timer_t timer;
    if (timer_create(CLOCK_REALTIME,&sev,&timer) == -1)
    {
        perror("Error in timer_create!\n");
        exit(EXIT_FAILURE);
    }
    if (timer_settime(timer,&ts,NULL) == -1)
    {
        perror("Error in timer_settime!\n");
        exit(EXIT_FAILURE);
    }
    struct timespec timetoWaitInLoop = { .tv_sec = 0,.tv_nsec = 300000000};
    for (int i=0; i<1000; ++i)
    {
        printf("I'm working!\n");
        nanosleep(&timetoWaitInLoop,NULL);
    }
}

当我将 timeForTimer 设置为 3 秒时,程序可以正常工作,2 秒内它仍然有效,但 1 秒内没有。 编译:gcc -Wall main.c -lrt

这是一个简短的例子

#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <stdlib.h>
#include <memory.h>
#include <unistd.h>

int main(int argc,char* argv[])
{
    struct sigevent sev;
    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIGSTOP;
    struct timespec timeForTimer = { .tv_sec = 1,.tv_nsec = 0}; // set time for timer here!
    struct itimerspec ts = { .it_interval = timeForTimer,&timer) == -1)
    {
        perror("Error in timer_create!\n");
        exit(EXIT_FAILURE);
    }
    if( timer_settime(timer,.tv_nsec = 300000000};
    for (int i=0; i<1000; ++i)
    {
        printf("I'm working! (PID) %d\n",getpid());
        nanosleep(&timetoWaitInLoop,NULL);
    }
}

在上面的例子中,只发生了一个 SIGSTOP 信号。使用命令 kill -18 发送 SIGCONT 后,不再有 SIGSTOP 信号。看起来我的计时器已解除。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)