0

After I stopped child processes with SIGSTOP, I want to execute the child processes every 3 seconds using SIGALRM, but the handler does not work. Here is my code:

#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
            }
        }
    }
}

I want to get as the result

sense 1 is working
sense 2 is not working 
sense 1 is not working 
sense 2 is working
.
.
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
karim
  • 63
  • 2
  • 9
  • 1
    A process stopped by SIGSTOP will not do *anything* until it receives a SIGCONT. You probably want to use [sigsuspend](https://man7.org/linux/man-pages/man2/sigsuspend.2.html) or [sigwaitinfo](https://man7.org/linux/man-pages/man2/sigwaitinfo.2.html) instead, or even better, find a way to not use signals at all. – zwol Oct 06 '20 at 01:04
  • yes i know ,but i am using SIGCONT in the handler but I don't know why it does not execute. – karim Oct 06 '20 at 01:08
  • Use of sigaction() instead of signal() is recommended. From "man signal" on Ubuntu 20.04: "The only portable use of signal() is to set a signal's disposition to SIG_DFL or SIG_IGN. The semantics when using signal() to establish a signal handler vary across systems (and POSIX.1 explicitly permits this variation); do not use it for this purpose." – TonyB Oct 06 '20 at 01:11
  • @karim The SIGALRM handler won't run until *after* the stopped process receives a SIGCONT sent by some process that isn't stopped. – zwol Oct 06 '20 at 01:15
  • Should `feuCouleurSenseBA = 1;` really be `Sense2 = 1;`? – Jonathan Leffler Oct 06 '20 at 02:12

2 Answers2

1

You might want to replace the signals you send from your parent process to its childs by SIGCONT (instead of SIGALRM): a process stopped with SIGSTOP will not be able to handle any kind of signals.

Here is what happens when I run a command, and I send a SIGSTOP to it (with Ctrl + Z):

$ sleep 360
^Z
[1]+  Stopped                 sleep 360
$ pkill -SIGINT sleep
# Does nothing

When the program is resumed, signals will be handled:

$ pkill -SIGCONT sleep
[1]-  Interrupt               sleep 360

Here is what happens with your program with the modified code:

$ ./a.out
sense 2 is working
sense 1 working
sense 2 is working
 sense 1 not working
sense 2 is working
sense 1 working
Anis Ladram
  • 173
  • 3
0

Since the child processes are stopped via SIGSTOP, they will only do anything when woken by sending SIGCONT, you should use

kill(pid1, SIGCONT);
kill(pid2, SIGCONT);

Setting the handler for SIGALRM won't affect anything until you send an alarm signal to your parent process. You haven't set an alarm with alarm() so you won't get an alarm signal from that. It is not clearly defined what happens if you use sleep(). Since the parent is not stuck waiting for SIGCONT, the parent sending the signal to itself won't help, especially as the handler that sends the signal isn't invoked.

Note that you are not supposed to call printf() from a signal handler — see How to avoid using printf() in a signal handler? for more information on that. If you do call printf(), you need to end the output with a newline to ensure it is printed — or use fflush().

Here is code that seems to work:

#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);
            }
        }
    }
}

I've used some code that is available in my SOQ (Stack Overflow Questions) repository on GitHub as files stderr.c and stderr.h in the src/libsoq sub-directory. This allows me to get PID and time information into messages printed using err_remark().

Sample output (source code alarm47.c, program alarm47):

alarm47: 2020-10-05 20:31:44.593 - pid=28446: Parent about to sleep
alarm47: 2020-10-05 20:31:44.593 - pid=28447: Child 1 at work - Sense1 = 1
alarm47: 2020-10-05 20:31:44.593 - pid=28448: Child 2 at work - Sense2 = 0
alarm47: 2020-10-05 20:31:47.597 - pid=28446: Parent woke up
alarm47: 2020-10-05 20:31:47.598 - pid=28446: Parent about to sleep
sense 2 is working
alarm47: 2020-10-05 20:31:47.598 - pid=28448: Child 2 - Sense2 now 1
sense 1 working
alarm47: 2020-10-05 20:31:47.598 - pid=28447: Child 1 - Sense1 now 0
alarm47: 2020-10-05 20:31:50.598 - pid=28446: Parent woke up
sense 2 is not working
alarm47: 2020-10-05 20:31:50.598 - pid=28446: Parent about to sleep
alarm47: 2020-10-05 20:31:50.598 - pid=28448: Child 2 - Sense2 now 0
sense 1 not working
alarm47: 2020-10-05 20:31:50.598 - pid=28447: Child 1 - Sense1 now 1
alarm47: 2020-10-05 20:31:53.601 - pid=28446: Parent woke up
sense 2 is working
sense 1 working
alarm47: 2020-10-05 20:31:53.601 - pid=28448: Child 2 - Sense2 now 1
alarm47: 2020-10-05 20:31:53.601 - pid=28446: Parent about to sleep
alarm47: 2020-10-05 20:31:53.601 - pid=28447: Child 1 - Sense1 now 0
alarm47: 2020-10-05 20:31:56.604 - pid=28446: Parent woke up
sense 2 is not working
alarm47: 2020-10-05 20:31:56.604 - pid=28448: Child 2 - Sense2 now 0
sense 1 not working
alarm47: 2020-10-05 20:31:56.605 - pid=28446: Parent about to sleep
alarm47: 2020-10-05 20:31:56.605 - pid=28447: Child 1 - Sense1 now 1
alarm47: 2020-10-05 20:31:59.606 - pid=28446: Parent woke up
alarm47: 2020-10-05 20:31:59.606 - pid=28446: Parent about to sleep
sense 2 is working
sense 1 working
alarm47: 2020-10-05 20:31:59.606 - pid=28448: Child 2 - Sense2 now 1
alarm47: 2020-10-05 20:31:59.606 - pid=28447: Child 1 - Sense1 now 0

Give or take the debug information, that's pretty much what you were after. Note that the sequence in which the two child processes respond is not guaranteed.

Note that the alarm handler is never called.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278