Bug 211123 - Throw C++ exception from a signal handler.
Summary: Throw C++ exception from a signal handler.
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 9.2-RELEASE
Hardware: Any Any
: --- Affects Many People
Assignee: freebsd-bugs mailing list
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-07-14 19:01 UTC by Chris Wittmann
Modified: 2017-04-23 18:21 UTC (History)
1 user (show)

See Also:


Attachments
Throwing C++ exception from a signal handler. (562 bytes, text/plain)
2016-07-14 19:01 UTC, Chris Wittmann
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
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 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.