0

I am currently learning about signals in C and have a small program, that is supposed to not terminate upon receiving the SIGINT signal using sigaction().

The code written below however does terminate, even though it looks fine to me. Maybe I am something missing. Does someone see, why it still terminates?

#include <signal.h>
#include <stdio.h>
#include <unistd.h>

void handle() { printf("%s%d%s", "I won't die....: ", getpid(), "\n"); }

int main() {
  struct sigaction sa;
  sa.sa_handler = handle;
  int k = 0;
  sigaction(SIGINT, &sa, NULL);
  // signal(SIGINT, handle); //signal works just fine

  while (k < 60) {
    printf("%s", "sleeping... \n");
    sleep(1);
    k = k + 1;
  }
}

Additional info: My OS is Windows, however I compile and execute the program in the Bash of a Linux subsystem.

alk
  • 69,737
  • 10
  • 105
  • 255
Imago
  • 521
  • 6
  • 29
  • 3
    You've not initialized the `sa` properly. See for example https://www.gnu.org/software/libc/manual/html_node/Sigaction-Function-Example.html – Antti Haapala -- Слава Україні Jun 23 '18 at 11:48
  • @AnttiHaapala, I just followed a tutorial on YT, most people there considered the video highly helpful + the person there appears to be a lecturer, so I guess he knows what he is doing. So what does not initialising sa properly do? – Imago Jun 23 '18 at 11:51
  • 1
    Well, time to comment that it is unhelpful and wrong. `sa` here is a variable of automatic storage duration, and therefore its contents are unspecified, besides the `sa.sa_handler`, i.e. all the other fields contain garbage. Who knows what it does. – Antti Haapala -- Слава Україні Jun 23 '18 at 11:56
  • @AnttiHaapala So, the question rather becomes, why do I need the sa_handler with for example a sa_flags = 0 together to catch the signal. Maybe I find something. – Imago Jun 23 '18 at 12:03
  • It's really not necessary to ask why providing uninitialised data to a function produces unpredictable results. I don't know which tutorial you're talking about, but you should maybe check it again; I'll bet there is a memset or something like it which initialises the `struct sigaction`. – rici Jun 23 '18 at 15:08
  • @rici, Why is it not necessary? There are unimaginable many cases where uninitialised or only partially initialised dat a works fine. My second comments specifies that. Regarding the bet: Why would you do that without any chance of winning? Instead of betting, you should either ask, what the tutorial was, if it provided the memset or as the best answer explain why flagset = 0 or memset is necessary. Simply providing a fix doesn't tell one anything. – Imago Jun 23 '18 at 18:41
  • Undefined behaviour is undefined ... – alk Jun 24 '18 at 07:45
  • Regarding a safe initialisation of `sa`: A simple `struct sigaction sa = {0};` would do the job. – alk Jun 24 '18 at 07:50
  • "*Maybe I find something.*" it's all in the relevant documentation. For Linux [this is the reference](http://man7.org/linux/man-pages/man2/sigaction.2.html). – alk Jun 24 '18 at 07:51

1 Answers1

2

Open the manual page of sigaction() and understand all the members of struct sigaction and fill all the members of struct sigaction.

struct sigaction {
            void     (*sa_handler)(int);
            void     (*sa_sigaction)(int, siginfo_t *, void *);
            sigset_t   sa_mask;
            int        sa_flags;
            void     (*sa_restorer)(void);
};

Here

struct sigaction sa;

As pointed by @AnttiHaapala here sa is a variable of automatic storage duration and you didn't initialize its members, it invokes undefined behavior as all the other fields contain garbage except sa.sa_handler

So you need to fill the other members of struct sigaction like

sa.sa_handler = handle;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);

Or initialize sa itself like

struct sigaction sa = {0};

Also it's not a good practice to write printf() statement inside signal handler, read here How to avoid using printf in a signal handler? .

Achal
  • 11,821
  • 2
  • 15
  • 37