TL;DR
(Visual Studio 2019, Windows 10 (so far tested on 1809LTSC, because this is my dev machine)
- We have an out-of-process COM server
- We set
COMGLB_EXCEPTION_DONOT_HANDLE_ANY - "Fatal" SEH exceptions are handled OK.
- "Non-Fatal" SEH exceptions, among these C++ excpetions, are randomly swallowed or handled by the COM/RPC runtime stack.
Does COMGLB_EXCEPTION_DONOT_HANDLE _ANY work reliably? Are there any additional settings?
Neccessary Background
When using COM, the RPC layer will catch (and possibly swallow) all Structured SEH Exceptions (which include C++ exceptions). Raymond explains this very well:
Historically, COM placed a giant try/except around your server’s methods. If your server encountered what would normally be an unhandled exception, the giant try/except would catch it and turn it into the error RPC_E_SERVERFAULT. It then marked the exception as handled, so that the server remained running ... Mind you, this was actually a disservice
Now there is a supposed solution, namely IGlobalOptions with setting COMGLB_EXCEPTION_DONOT_HANDLE_ANY.
This is supposed to (to quote The Old New):
... then go ahead and let the process crash.” In Windows 7, you can ask for the even stronger COMGLB_EXCEPTION_DONOT_HANDLE_ANY, which means “Don’t even try to catch ‘nonfatal’ exceptions.”
You can even find this recommendation in the docs:
It's important for applications that detect crashes and other exceptions that might be generated while executing inbound COM calls, ... to set COMGLB_EXCEPTION_HANDLING to COMGLB_EXCEPTION_DONOT_HANDLE to disable COM behavior of catching exceptions.
And the option is explained as:
COMGLB_EXCEPTION_DONOT_HANDLE_ANY:
- When set and a fatal exception occurs in a COM method, this causes the COM runtime to not handle the exception. (caveat A)
- When set and a non-fatal exception occurs in a COM method, this causes the COM runtime to create a Windows Error Reporting (WER) dump and terminate the process. Supported in Windows 7 and later. (caveat B)
And here's the thing
Neither of the above two statements is really accurate, but specifically for any non fatal exception, which C++ exceptions are, we get random behavior:
I have set up a simple client / server COM Test Program in VS2019 and intentionally generate an unhandled C++ exception: There are two modes at runtime, seemingly at random:
- Server is terminated by the COM/RPC stack and we get an ID 1000 entry in the event log with the exceptioncode
0xe06d7363(and a WER dump is written). The client gets 0x800706BE HRESULT in this case.- This is the advertised behavior.
- Starting the client -> server a second (or third, ...) time, the C++ Exception DOES NOT terminate the server, and the client gets
0xe06d7363as HRESULT for its server call. No event log entry written!
For those "fatal" SEH exceptions the termination happens reliably; but not for the non-fatal ones.
What is going on here?