Bug 211123

Summary: Throw C++ exception from a signal handler.
Product: Base System Reporter: Chris Wittmann <cwittmann>
Component: kernAssignee: freebsd-bugs (Nobody) <bugs>
Status: New ---    
Severity: Affects Many People CC: jilles
Priority: ---    
Version: 9.2-RELEASE   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
Throwing C++ exception from a signal handler. none

Description Chris Wittmann 2016-07-14 19:01:13 UTC
Created attachment 172529 [details]
Throwing C++ exception from a signal handler.

I'm writing a multithreaded C++ server to run on FreeBSD AMD64 so I need to throw C++ exceptions from within a signal handler.  Windows supports C++ exceptions from as signal handler as expected.  On FreeBSD 10.2, even the -fnon-call-exceptions switch doesn't do a thing.

Is there a way to build an AMD64 kernel that supports signal-handler exception throwing?


// Exceptions.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <signal.h>


using namespace std;

void handler(int signal)
{
    throw 23;
}


int _tmain(int argc, _TCHAR* argv[])
{
    signal(SIGINT, handler);
    signal(SIGSEGV, handler);

    try
    {
        int* p = NULL;
        *p += *p;

        //raise(SIGINT);
        cout << "... no catchie ..." << endl;
    }
    catch (...)
    {
        cout << "CAUGHT THE MOFO!" << endl;
    }

	return 0;
}
Comment 1 Jilles Tjoelker freebsd_committer freebsd_triage 2016-07-15 21:28:57 UTC
This could be because FreeBSD's signal trampoline does not have proper unwind information since it is not part of a proper ELF object. Debuggers such as gdb have a special case for this but the unwinder for C++ exceptions does not.

If you really want to do this, a workaround could be a sigjmp_buf in thread-local storage.

The null pointer dereference does not raise SIGSEGV because clang detects it as undefined behaviour, replacing it with an ud2 instruction and deleting everything after it.

Apart from that, throwing exceptions from arbitrary points in the code is rather unsafe. Per gcc's documentation, even -fnon-call-exceptions will not handle asynchronous exceptions. Safely interrupting code at any location requires process isolation or severe restrictions on the code.