0

I am trying to send a signal from a child process to a parent process in C, and I've got a signal handler setup:

void handler(int signumber,siginfo_t* info,void* nonused)
{
    printf("Signal with number %i has arrived\n",signumber);
    switch (info->si_code){
        case SI_USER: printf("Process (PID number %i) sent the signal (calling kill)\n",info->si_pid); break;
        case SI_TIMER: printf("It was sent by a timer\n");
            printf("Additional data: %i\n",info->si_value.sival_int);
            //  timer_delete(t_id); //stops timer
            break;
        case SI_QUEUE: printf("It was sent by a sigqueue, sending process (PID %i)\n",info->si_pid);
            printf("Additional value: %i\n",info->si_value.sival_int);
            //  struct student* d=(struct student*)info->si_value.sival_ptr;
            //  printf("Additional value: %s, %i\n",d->name,d->year);
            break;
        default: printf("It was sent by something else \n");
    }
}

And the attempt to send a signal with additional data using sigqueue:

struct sigaction action;

action.sa_sigaction = handler;
sigemptyset(&action.sa_mask);
action.sa_flags=SA_SIGINFO;
if (sigaction(SIGTERM, &action, NULL) < 0) 
{
    perror("Sigaction failed");
    exit(1);
}
pid = fork();
if (pid == -1) 
{
    perror("Forking error");
    exit(EXIT_FAILURE);
}
if (pid == 0) //child process
{
            printf("Child process (PID %i), will send a SIGTERM to parent %i\n",getpid(),getppid());
//            sleep(1);
//            kill(getppid(),SIGTERM); //this works

            //sending an integer as an additional data
            sleep(1);
            union sigval s_value_int={5};
            sigqueue(getppid(),SIGTERM,s_value_int);
            printf("Child process ended\n");
}
else
{
            printf("Parent (PID %i) waits for a signal from child (PID %i) \n",getpid(),pid);
            pause();
            wait(NULL);
            printf("Parent process ended\n");
}

The problem is, I am not receiving any kind of output (from the handler) and the parent process freezes forever (waiting for the signal from the child because of the pause() call), therefore I suspect that the signal never arrives. "Child process ended" gets output to the console.

Interestingly, if I send the signal via kill(), the parent receives it just fine and the handler prints out the additional info too. Unfortunately I need the sigqueue alternative, because I must send an additional integer as data to the parent. I read about possible signal losses because of too many signals coming in and they get queued up, could that be the problem in my case too? If so, what could be done to fix it? Many thanks

Toni Nagy
  • 133
  • 2
  • 11
  • Looks OK except for an issue: `action` struct need to be zero initialized as you're only some some fields but not all. You can do: `struct sigaction action = {0};`. – P.P Apr 18 '20 at 16:19
  • There are many functions that are NOT to be used in a signal handler. `printf()` is one of the functions not to be used. Suggest reading: `man 7 signals` and `man 7 signal-safety`/ Note `write()` can be used instead of `printf()` – user3629249 Apr 19 '20 at 16:14
  • Well, as things have escalated: the exact code still doesn't run well on my PC in CLion IDE (if that's relevant at all) and after uploading it to the university's server, it does receive the signal and prints out the info just fine. Peculiar. – Toni Nagy Apr 19 '20 at 18:03
  • Compiling with gcc 7.2.0 locally and gcc 6.5 on the server – Toni Nagy Apr 19 '20 at 18:05

0 Answers0