1

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, siginfo_t* SI, 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, &set, 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, &sa, 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, 0, &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, .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, 0, &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! (PID) %d\n", getpid());
            nanosleep(&timeToWaitInLoop,NULL);
        }
    }

在上面的例子中,只SIGSTOP出现了一个信号。发送SIGCONT命令kill -18 <pid>后没有更多SIGSTOP信号。看起来我的计时器被解除了。

4

0 回答 0