Non-local jump in C language signal processing program?

refer to Exceptions in C with Longjmp and Setjmp to write the following program:

-sharpinclude <setjmp.h>
-sharpinclude <signal.h>
-sharpinclude <stdio.h>

jmp_buf ex_buf__;

-sharpdefine TRY do{ if(!setjmp(ex_buf__)) {
-sharpdefine CATCH } else {
-sharpdefine ETRY } } while(0)
-sharpdefine THROW longjmp(ex_buf__, 1)

void sigint_handler(int sig) {
  THROW;
}


int main(void) {
  if (signal(SIGINT, sigint_handler) == SIG_ERR) {
    return 0;
  }

  TRY {
    while (1) {
      printf("Run...\r");
    }
    /* raise(SIGINT); */
  } CATCH {
    printf("KeyboardInterrupt");
  }
  ETRY;

  return 0;
}

originally hoped that when the program was running, pressing Ctrl-C would get the output: KeyboardInterrupt .

however, the program crashes at actual run time. The output before the crash is still Run. .

if you replace the while part with raise (SIGINT) , you can get the desired result.

Why is this? Does it have anything to do with the endless cycle?

compilation environment:

  • Compiler:

    gcc version 7.2.0 (x86_64-win32-seh-rev1, Built by MinGW-W64 project)
    clang version 5.0.1 (tags/RELEASE_501/final)
    Target: x86_64-pc-windows-msvc
    Thread model: posix

    the result of the two runs is the same.

  • operating system:

    Microsoft Windows 7
Mar.23,2021

unless the floating point number is abnormal and Windows explicitly forbids calling longjmp in the signal handling function, the process will crash (exception C0000029 INVALID_UNWIND_TARGET ).

if you must call longjmp in signal handler, to avoid the msvcr implementation library, you can use gcc's _ _ builtin__longjmp , as follows

.
-sharpinclude <setjmp.h>
-sharpinclude <signal.h>
-sharpinclude <stdio.h>

jmp_buf ex_buf__;

void sigint_handler(int sig)
{
    __builtin_longjmp(ex_buf__, 1);
}

int main(void)
{
    if (signal(SIGINT, sigint_handler) == SIG_ERR) {
        return 0;
    }

    if (!__builtin_setjmp(ex_buf__)) {
        while (1) {
            printf("Run...\r");
        }
    } else {
        //  print()  fprintf(stdout, ...)
        fprintf(stderr, "KeyboardInterrupt\n");
    }
    
    return 0;
}

Note: after calling _ builtin_longjmp , you can no longer use printf , because the signal interruption has destroyed its internal state. Continuing to print to standard output (stdout) will cause the process to crash.

of course, it's best not to use longjmp and other non-asynchronous security functions in signal handler to avoid security vulnerabilities or strange problems.

reference
[1]. https://docs.microsoft.com/en.
[2]. https://wiki.sei.cmu.edu/conf.

Menu