-2

I was trying following signal handler program , referring from an online tutorial , but it does not seems working , what is wrong with my code:

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

typedef void (*SignalHandlerPointer)(int);

static void UsrHostSigAbort(int pSignal)
{
        //stopService();
    printf("pankaj");
}
void HandleHostSignal()
{
        struct sigaction satmp;
        memset(&satmp, '\0' , sizeof(satmp));
        SignalHandlerPointer usrSigHandler;
        satmp.sa_flags &= ~SA_SIGINFO;
        satmp.sa_handler = UsrHostSigAbort;
        usrSigHandler = sigaction (SIGINT , &satmp, NULL);
}

void main()
{
HandleHostSignal();

while(1)
{
sleep(1);
}
}

I am compiling and running this program in ubuntu.

pankaj kushwaha
  • 369
  • 5
  • 20
  • What operating system are you using? – Ari0nhh Oct 25 '16 at 04:54
  • @Ari0nhh it is ubuntu , updated the Q with this information. – pankaj kushwaha Oct 25 '16 at 04:55
  • 1
    Note the discussion in [How to avoid using `printf()` in a signal handler?](http://stackoverflow.com/questions/16891019/) It probably isn't the cause of your trouble, but you should be aware of the issues described. – Jonathan Leffler Oct 25 '16 at 05:04
  • @Jonathan : Thanks for information :) – pankaj kushwaha Oct 25 '16 at 05:07
  • 1
    Doesn't your compiler shriek at you about assigning integers to pointers to functions? `sigaction()` returns an `int`; it is `signal()` that returns a `SignalHandlerPointer`. You've not used `sigemptyset(&satmp.sa_mask);` — that might matter. Your assignment to `satmp.sa_flags` is a no-op, I believe. – Jonathan Leffler Oct 25 '16 at 05:08
  • The rest of your problem is that you're not hitting the interrupt key often enough. You don't end your output with a newline, or use `fflush(stdout)`, so nothing appears until the buffer is full, which probably takes anywhere from 80 to 640 interrupts, give or take a few. (It depends on the value of BUFSIZ / 6 — you have to fill BUFSIZ with that many 6-byte strings.) Or you can add a newline to your output — that's probably simpler. – Jonathan Leffler Oct 25 '16 at 05:12
  • @JonathanLeffler : i tried this time hitting ctrl-c multiple time , and fixing return value problem that you mention in previous comment , but still same result. – pankaj kushwaha Oct 25 '16 at 05:17
  • 1
    Since you're on Ubuntu, GCC complained about `void main()`, didn't it? Pay attention to your compiler. If it warns, it is right — it knows a lot more about C than you do at this stage. If it didn't complain, you aren't compiling with enough warning flags. You need `gcc -Wall -Wextra` and a clean compilation. – Jonathan Leffler Oct 25 '16 at 05:20
  • It's just a debug issue. You shouldn't be calling `printf` at all in the signal handler. But if you do you need to at least `fflush` stdout or end the string with a newline to see the output. Do that and your program should behave as expected. – kaylum Oct 25 '16 at 05:23
  • Also note that `satmp.sa_flags &= ~SA_SIGINFO;` is pointless. It's trying to clear a bit from a variable that is 0 anyway (ie, no bits to clear). – kaylum Oct 25 '16 at 05:25
  • @JonathanLeffler: thanks for information , i will take care of compiler warnings – pankaj kushwaha Oct 25 '16 at 05:25
  • @kaylum: i have commented printf itself , but still same problem , i also checked flags , but same problem. – pankaj kushwaha Oct 25 '16 at 05:26
  • What do you mean "same problem"? If you comment out the `printf` then nothing visible will happen when you press ctrl-c. Instead, change the `printf` to `write(STDOUT_FILENO, "pankaj\n", strlen("pankaj\n"));` – kaylum Oct 25 '16 at 05:28
  • Read *carefully* [signal(7)](http://man7.org/linux/man-pages/man7/signal.7.html) and understand that `` is *buffering* so use [fflush(3)](http://man7.org/linux/man-pages/man3/fflush.3.html) – Basile Starynkevitch Oct 25 '16 at 05:34

1 Answers1

3

This code — which is basically only a trivial variant on your code — runs correctly on macOS Sierra 10.12.1:

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

static void UsrHostSigAbort(int pSignal)
{
    // stopService();
    // Using printf is not good - see: http://stackoverflow.com/questions/16891019/
    // It will suffice for this code, however.
    printf("pankaj %d\n", pSignal);
}

static void HandleHostSignal(void)
{
    struct sigaction satmp;
    sigemptyset(&satmp.sa_mask);
    satmp.sa_flags = 0;
    satmp.sa_handler = UsrHostSigAbort;
    sigaction(SIGINT, &satmp, NULL);
}

int main(void)
{
    HandleHostSignal();

    while (1)
    {
        sleep(1);
        putchar('.');
        fflush(stdout);
    }
}

Example output (program called sig19):

$ ./sig19
......^Cpankaj 2
.....^Cpankaj 2
....^Cpankaj 2
...^Cpankaj 2
..^Cpankaj 2
.^Cpankaj 2
..................^\Quit: 3
$

I used the quit key (^\ on my terminal) to stop the program.

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