What is the difference between MinGW SEH and MinGW SJLJ?

I discovered one difference between SJLJ and SEH exception handling in MinGW-w64: C signal handlers set by signal() function do not work in SJLJ version as soon as at least one try{} block gets executed at the run time. Since this issue does not seem to be described anywhere, I am putting it here for the record.

The following example (test_signals.cpp) demonstrates this.

// This sample demonstrates how try {} block disables handler set by signal()
// on MinGW-w64 with GCC SJLJ build
#include <signal.h>
#include <iostream>

int izero = 0;

static void SIGWntHandler (int signum)//sub_code)
{
  std::cout << "In signal handler, signum = " << signum << std::endl;
  std::cout << "Now exiting..." << std::endl;
  std::exit(1);
}

int main (void)
{
  std::cout << "Entered main(), arming signal handler..." << std::endl;
  if (signal (SIGSEGV, (void(*)(int))SIGWntHandler) == SIG_ERR)
    std::cout << "signal(OSD::SetSignal) error\n";
  if (signal (SIGFPE, (void(*)(int))SIGWntHandler) == SIG_ERR)
    std::cout << "signal(OSD::SetSignal) error\n";
  if (signal (SIGILL, (void(*)(int))SIGWntHandler) == SIG_ERR)
    std::cout << "signal(OSD::SetSignal) error\n";

  // this try block disables signal handler...
  try { std::cout << "In try block" << std::endl; } catch(char*) {}

  std::cout << "Doing bad things to cause signal..." << std::endl;
  izero = 1 / izero; // cause integer division by zero
  char* ptrnull = 0;
  ptrnull[0] = '\0'; // cause access violation

  std::cout << "We are too lucky..." << std::endl;
  return 0;
}

Builds with:

g++ test_signals.cpp -o test_signals.exe

The expected output is:

Entered main(), arming signal handler...
In try block
Doing bad things to cause signal...
In signal handler, signum = 8
Now exiting...

The actual output when I build with MigGW-w64 SJLJ variant is:

Entered main(), arming signal handler...
In try block
Doing bad things to cause signal...

The application gets terminated silently after some delay. That is, signal handler does not get called. If try{} block is commented out, signal handler gets called properly.

When using MinGW-w64 SEH variant, it behaves as expected (signal handler gets called).

I do not have clear idea of why this problem occurs, thus will be grateful if someone can give an explanation.


SJLJ and SEH are two different exception handling systems.

For the specific differences, the resources you've already seen cover everything.

However, as for which one is better to install, go with SJLJ unless you know that you need SEH.

2019 Update: On modern systems, there's no reason to use SJLJ, so the advice above should probably be flipped. SEH is more common now. Ultimately though, it doesn't really matter, since it's easy to switch between the two.

SJLJ

SJLJ is more widely supported across architectures, and is more robust. Also, SJLJ exceptions can be thrown through libraries that use other exception handling systems, including C libraries. However, it has a performance penalty.

SEH

SEH is much more efficient (no performance penalty), but unfortunately is not well-supported. SEH exceptions will cause bad things to happen when thrown through libraries that do not also use SEH.

As far as your code is concerned, there are no real differences. You can always switch compilers later if you need to.

Tags:

C++

C

Mingw

Qt