1

I am using the gcc of Mac right now. The program below runs well. Here I mean when I press control+c, terminal shows " now got a SIGINT signal\n":

#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void handler(int s)
{
       if (s == SIGINT) printf(" now got a SIGINT signal\n");
}
int main()
{
        signal(SIGINT, handler);
loop:
/* spin here, waiting for ctrl-c */
          goto loop;
}

However, when I add one line, something strange happened:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void handler(int s)
{
       if (s == SIGINT) printf(" now got a SIGINT signal\n");
}
int main()
{
printf("process id is %d ",getpid());
        signal(SIGINT, handler);
loop:
/* spin here, waiting for ctrl-c */
          goto loop;
}

The terminal doesn't show "process id is...", but after I press ^c, the terminal outputs ^Cprocess id is 13888 now got a SIGINT signal. This really confuses me. In fact, the output is really unusable; the function is a simplicity of code as below:

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
void sigroutine(int dunno) {
switch (dunno) {
case 1:
printf("Get a signal -- SIGHUP ");
break;
case 2:
printf("Get a signal -- SIGINT ");
break;
case 3:
printf("Get a signal -- SIGQUIT ");
break;
}
return;
}
int main() {
printf("process id is %d ",getpid());
signal(SIGHUP, sigroutine); 
signal(SIGINT, sigroutine);
signal(SIGQUIT, sigroutine);
for (;;) ;
}

Its output on my terminal seems to be nothing. Whatever I input, it never response. I begin to delete sentence one by one, and replace switch with if, replace for with goto and delete the getpid(). Finally, I don't why it can respond to control+c. However the behavior of getpid() is really weird to me. Could you explain to me about this?

I also tried only output getpid() without signal(). It works well.

BTW: how can I rerun the program without opening another terminal since Ctrl+c is useless.

Jonathan Leffler
  • 666,971
  • 126
  • 813
  • 1,185
Weiheng Li
  • 565
  • 7
  • 18
  • See [How to avoid using `printf()` in a signal handler](http://stackoverflow.com/questions/16891019/how-to-avoid-using-printf-in-a-signal-handler) for the strict rules. In your current code, there actually isn't much to worry about, but you should be aware of the issues. – Jonathan Leffler Sep 05 '16 at 02:03
  • Mac OS X doesn't reset the signal handler to default automatically, even with `signal()` instead of `sigaction()` — and the C and POSIX standards bless this — so you cannot send an interrupt, quit or hangup to your third program usefully; you probably need to send term. There isn't a way to do that from the keyboard, so you will need to use a separate terminal to run the `kill` command to terminate the process (or close the window). Be wary when handling signals — if you don't leave an escape route, processes continue running. – Jonathan Leffler Sep 05 '16 at 02:04
  • @JonathanLeffler thanks, your answer is on the point. – Weiheng Li Sep 05 '16 at 02:09
  • 2
    You can't call `printf` from a signal handler. The `printf` function is not re-entrant. – David Schwartz Sep 05 '16 at 02:13

2 Answers2

3

The output from the first printf is buffered. Either add a \n, or use fflush() to force the buffer to be flushed.

See here for more description: Why does printf not flush after the call unless a newline is in the format string?

Community
  • 1
  • 1
John3136
  • 27,345
  • 3
  • 44
  • 64
  • Ok, thank you. If the last block of program works well in your terminal? – Weiheng Li Sep 05 '16 at 02:00
  • @WeihengLi I haven't actually tried your code, I just know "thats how things work"... Don't forget to upvote and/or accept the answer if it is helpful. – John3136 Sep 05 '16 at 02:03
2

For first part of your concern - in main method please replace

printf("process id is %d ",getpid());

with

printf("process id is %d\n",getpid());

Here is the reason: Why does printf not flush after the call unless a newline is in the format string?

Printf ideally buffers characters - with \n or newline we are instructing it to flush (it is finally printing instead of accumulating/buffering what to print) ... please note that the printf inside your handler has a new line ... that explains why you were seeing the pid after hitting CTRL+C.

Community
  • 1
  • 1
  • It wasn't my downvote, but … What have you added that wasn't already provided by [John3136](http://stackoverflow.com/users/857132/john3136) in his [answer](http://stackoverflow.com/a/39322997/)? – Jonathan Leffler Sep 05 '16 at 02:08
  • Can you explain the -1 please? Thanks. – Suraiya Khan Sep 05 '16 at 02:10
  • I have not seen it - I was still typing. – Suraiya Khan Sep 05 '16 at 02:11
  • Some people around here are quicker on the down-votes than me. I'm guessing that someone thought "he copied what John3136 said". The difference in time was almost fifteen minutes; that's in the borderline zone (roughly 10-30 minutes) where it might have been copied, or it might be independent work. More than 30 minutes later, it is usually copying (not always, but usually). Also, FWIW, asking for explanations for down-votes is seldom constructive — you seldom get any response from the down-voter. That's speaking from a number of years experience here on SO. – Jonathan Leffler Sep 05 '16 at 03:23
  • Thanks Jonathan Leffler for the explanation and patience with me. I am new here and still learning what is expected. I was at a loss regarding what was wrong with my answer. I do not use C since 2006 (please have a look at my profile) ... still my memory is pretty good and I decided to answer ... to make sure I am thorough I tested the code on my system before posting without relying on my memory and gathered the link from SO to avoid verbose explanation. – Suraiya Khan Sep 05 '16 at 03:39