C中的SIGALRM不在处理程序中执行

C中的SIGALRM不在处理程序中执行,c,linux,bash,multithreading,signals,C,Linux,Bash,Multithreading,Signals,在我使用SIGSTOP停止子进程之后,我希望使用SIGALRM每隔3秒执行一次子进程, 但是处理程序不起作用。这是我的密码: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> void singAlrm(int sig) { printf("HELLO from SI

在我使用SIGSTOP停止子进程之后,我希望使用SIGALRM每隔3秒执行一次子进程, 但是处理程序不起作用。这是我的密码:

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

void singAlrm(int sig)
{
    printf("HELLO from SIGALRM");
    kill(getpid(), SIGCONT);
}

int main()
{
    int Sense1 = 1;
    int Sense2 = 0;

    int pid1 = fork();
    signal(SIGALRM, singAlrm);
    if (pid1 == 0)// fils1
    {
        while (1)
        {
            kill(getpid(), SIGSTOP);
            if (Sense1 == 1)
            {
                printf("sense 1 working \n");
                Sense1 = 0;
            }
            else
            {
                printf(" sense 1 not working\n");
                Sense1 = 1;
            }
        }
        exit(0);
    }
    else// pere
    {
        int pid2 = fork();
        if (pid2 == 0)
        {
            while (1)
            {
                kill(getpid(), SIGSTOP);
                if (Sense2 == 1)
                {
                    printf("sense 2 is not working\n");
                    Sense2 = 0;
                }
                else
                {
                    printf("sense 2 is working\n");
                    feuCouleurSenseBA = 1;
                }
            }
            exit(0);
        }
        else
        {
            while (1)
            {
                sleep(3);

                signal(SIGALRM, singAlrm);
                kill(pid2, SIGALRM);
                kill(pid1, SIGALRM);// here I have a problem when I call SIGALRM
            }
        }
    }
}

您可能希望用
SIGCONT
(而不是
SIGALRM
)替换从父进程发送给其子进程的信号:用
SIGSTOP
停止的进程将无法处理任何类型的信号

下面是当我运行一个命令并向它发送一个
SIGSTOP
时发生的情况(使用
Ctrl+Z
):

$sleep 360
^Z
[1] +停止睡眠360
$pkill-信号睡眠
#无所事事
当程序恢复时,信号将被处理:

$pkill-SIGCONT睡眠
[1] -中断睡眠360
以下是使用修改后的代码的程序所发生的情况:

$/a.out
第二感正在发挥作用
第1感工作
第二感正在发挥作用
感觉1不工作
第二感正在发挥作用
第1感工作

由于子进程是通过
SIGSTOP
停止的,它们只有在通过发送
SIGCONT
唤醒时才会执行任何操作,您应该使用

kill(pid1, SIGCONT);
kill(pid2, SIGCONT);
在向父进程发送报警信号之前,为
SIGALRM
设置处理程序不会影响任何事情。您没有设置警报,因此不会从中收到警报信号。它没有明确定义如果你使用它会发生什么。由于父级没有被困在等待
SIGCONT
,因此将信号发送到自身的父级将不会有帮助,尤其是在发送信号的处理程序未被调用的情况下

请注意,您不应该从信号处理程序调用
printf()
,请参阅以了解更多信息。如果确实调用了
printf()
,则需要以换行符结束输出,以确保它已被打印-或者使用
fflush()

下面是似乎有效的代码:

#include "stderr.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>

static void singAlrm(int sig)
{
    printf("HELLO from SIGALRM %d\n", sig);
    //kill(getpid(), SIGCONT);
}

int main(int argc, char **argv)
{
    if (argc > 0)
        err_setarg0(argv[0]);
    err_setlogopts(ERR_PID|ERR_MILLI);
    int Sense1 = 1;
    int Sense2 = 0;

    int pid1 = fork();
    signal(SIGALRM, singAlrm);
    if (pid1 == 0)// fils1
    {
        err_remark("Child 1 at work - Sense1 = %d\n", Sense1);
        while (1)
        {
            kill(getpid(), SIGSTOP);
            if (Sense1 == 1)
            {
                printf("sense 1 working\n");
                Sense1 = 0;
            }
            else
            {
                printf("sense 1 not working\n");
                Sense1 = 1;
            }
            err_remark("Child 1 - Sense1 now %d\n", Sense1);
        }
        exit(0);
    }
    else// pere
    {
        int pid2 = fork();
        if (pid2 == 0)
        {
            err_remark("Child 2 at work - Sense2 = %d\n", Sense2);
            while (1)
            {
                kill(getpid(), SIGSTOP);
                if (Sense2 == 1)
                {
                    printf("sense 2 is not working\n");
                    Sense2 = 0;
                }
                else
                {
                    printf("sense 2 is working\n");
                    Sense2 = 1;
                }
                err_remark("Child 2 - Sense2 now %d\n", Sense2);
            }
            exit(0);
        }
        else
        {
            while (1)
            {
                err_remark("Parent about to sleep\n");
                sleep(3);
                err_remark("Parent woke up\n");
                //signal(SIGALRM, singAlrm);
                kill(pid2, SIGCONT);
                kill(pid1, SIGCONT);
            }
        }
    }
}
给出或获取调试信息,这正是您所追求的。请注意,两个子进程响应的顺序不能保证


请注意,从未调用报警处理程序。

由SIGSTOP停止的进程在收到SIGCONT之前不会执行任何操作。您可能想使用或相反,甚至更好,找到一种根本不使用信号的方法。是的,我知道,但我在处理程序中使用了SIGCONT,但我不知道它为什么不执行。建议使用sigaction()而不是signal()。Ubuntu 20.04上的“man signal”中写道:“signal()的唯一可移植用途是将信号的配置设置为SIG_DFL或SIG_IGN。使用signal()建立信号处理程序时的语义因系统而异(POSIX.1明确允许这种变化);不要将其用于此目的。”@karim在停止的进程收到某个未停止的进程发送的SIGCONT之前,SIGALRM处理程序不会运行真的是
Sense2=1
#include "stderr.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>

static void singAlrm(int sig)
{
    printf("HELLO from SIGALRM %d\n", sig);
    //kill(getpid(), SIGCONT);
}

int main(int argc, char **argv)
{
    if (argc > 0)
        err_setarg0(argv[0]);
    err_setlogopts(ERR_PID|ERR_MILLI);
    int Sense1 = 1;
    int Sense2 = 0;

    int pid1 = fork();
    signal(SIGALRM, singAlrm);
    if (pid1 == 0)// fils1
    {
        err_remark("Child 1 at work - Sense1 = %d\n", Sense1);
        while (1)
        {
            kill(getpid(), SIGSTOP);
            if (Sense1 == 1)
            {
                printf("sense 1 working\n");
                Sense1 = 0;
            }
            else
            {
                printf("sense 1 not working\n");
                Sense1 = 1;
            }
            err_remark("Child 1 - Sense1 now %d\n", Sense1);
        }
        exit(0);
    }
    else// pere
    {
        int pid2 = fork();
        if (pid2 == 0)
        {
            err_remark("Child 2 at work - Sense2 = %d\n", Sense2);
            while (1)
            {
                kill(getpid(), SIGSTOP);
                if (Sense2 == 1)
                {
                    printf("sense 2 is not working\n");
                    Sense2 = 0;
                }
                else
                {
                    printf("sense 2 is working\n");
                    Sense2 = 1;
                }
                err_remark("Child 2 - Sense2 now %d\n", Sense2);
            }
            exit(0);
        }
        else
        {
            while (1)
            {
                err_remark("Parent about to sleep\n");
                sleep(3);
                err_remark("Parent woke up\n");
                //signal(SIGALRM, singAlrm);
                kill(pid2, SIGCONT);
                kill(pid1, SIGCONT);
            }
        }
    }
}