0

Here's my code:

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

jmp_buf buf;

void handler(int s);

int main(int argc, char **argv) {
    signal(SIGINT, handler);
    if (setjmp(buf)) {
        printf("back again!\n");
        return 0;
    } else {
        printf("first here.\n");
    }

    for (;;) {}
}

void handler(int s) {
    longjmp(buf, 1);
}

I compile it under VS 2012 on Windows 8 64bit. Every time I press Control+C, the program doesn't reboot as expected but stops working. Could anybody help me?

Zhe Chen
  • 2,918
  • 4
  • 23
  • 39

2 Answers2

2

From the current C standard:

If the signal occurs other than as the result of calling the abort or raise function, the behavior is undefined if the signal handler refers to any object with static or thread storage duration that is not a lock-free atomic object other than by assigning a value to an object declared as volatile sig_atomic_t, or the signal handler calls any function in the standard library other than the abort function, the _Exit function, the quick_exit function, or the signal function with the first argument equal to the signal number corresponding to the signal that caused the invocation of the handler.

you are using an object with static storage duration that is not in the list of allowed types (buf) and you use a function of the standard library that is not in the list of allowed functions (longjmp).

Ross
  • 1,313
  • 4
  • 16
  • 24
Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
0

I think what you want is this.

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

static int k;

void
handler(int s)
{
    k++;
}

int
main(int argc, char *argv[])
{
    int n = 0;

    signal(SIGINT, handler);

    while (1) {
        if (k > n) { 
            printf("handler got called %d\n", k);
            n = k;
            if (k == 5) {
                break; /* break out after five control-c */
            }
        }
    }

    exit(0);
}

Try it out and let me know how it goes.

Arun Taylor
  • 1,574
  • 8
  • 5
  • As of the text cited in my answer you can't access `k` from the signal handler. You'd have to use a `volatile sig_atomic_t` to communicate between signal handler and `main`. – Jens Gustedt Jul 26 '13 at 06:41
  • @Jens Gustedt, Before posting the code, I compiled it and ran it on my OpenBSD system and it works as intended. Are you saying that you tried it in your environment and it doesn't work? What environment are you using? – Arun Taylor Jul 26 '13 at 14:51
  • No, I am saying that you can't expect your code to be portable. (Did you run it some thousand times to check that it works reliably?) the phrase that I am citing gives you the frame from the standard. Doing anything else results in UB. So it might work on one platform and format the hard disk on another. But as I said, there is an easy repair for this, use `volatile sig_atomic_t`. This is supposed to be an integer type that "does the right thing". On most platforms this is in fact `int`, but the `volatile` is also important, here. Your code must be sure to always have the latest value of `k`. – Jens Gustedt Jul 26 '13 at 15:02