jrfonseca / drmingw

Postmortem debugging tools for MinGW.
GNU Lesser General Public License v2.1
279 stars 56 forks source link

Information about multiple threads and exchndl requested #54

Closed acidtonic closed 3 years ago

acidtonic commented 3 years ago

In one of the closed issues here, I noticed a comment that the Exchndl_Init handler doesn't work for all threads.

I have an app with many many threads and was curious if I am still able to achieve what I am after with Exchndl bundled with the program. I need to make sure a crash from any of the threads properly triggers a RPT file but I am not seeing that.

Were you hinting that multiple threads are not supported? Or just that each thread needs to register the handler when it starts? Are there any race conditions on setting a custom report file location with multiple threads or should only the main (1st) thread do that before spawning others?

Am I supposed to get an RPT file for unhandled exceptions which just print to the console and then call abort/terminate? Or is this purely for segfaults?

Appreciate any info.

jrfonseca commented 3 years ago

I'm afraid ExcHnd only supports one thread at this moment.

This is due to how SetUnhandledExceptionFilter() works, and I'm not sure if there's a good way to call SetUnhandledExceptionFilter on every thread. It might be possible to somehow get SetUnhandledExceptionFilter() called on every thread, but I don't have the time (or personal need) to pursuing that.

If you do

LoadLibrary("exchndl.dll");
pfnExcHndlInit = GetProcAddress("ExcHndlInit");
pfnExcHndlInit()

then only the thread where ExcHndlInit() is called will report uncaught exceptions.

It should report any uncaught exception. Not just segfaults.

But you're right, multi-threading is an important question. I'll update the README file to explain this.

alvinhochun commented 3 years ago

DllMain is called with DLL_THREAD_ATTACH on every new threads after the DLL has been loaded, perhaps it can be used? Obviously this doesn't handle threads created before loading the DLL and you'll have to keep a record of thread IDs for cleaning up on DLL_THREAD_DETACH (a simple linked list should be fine though) but it would be an improvement.

jrfonseca commented 3 years ago

Yes, hooking DLL_THREAD_ATTACH would be better than nothing.

liaoxuewei commented 2 years ago

Yes, hooking DLL_THREAD_ATTACH would be better than nothing.

Is there a solution to this requirement now?

lb90 commented 2 years ago

Hi @jrfonseca, I'd like to ask for informations

This is due to how SetUnhandledExceptionFilter() works, and I'm not sure if there's a good way to call SetUnhandledExceptionFilter on every thread. It might be possible to somehow get SetUnhandledExceptionFilter() called on every thread, but I don't have the time (or personal need) to pursuing that.

the documentation for SetUnhandledExceptionFilter says that it works globally for all threads. Can you give more insights as to what can be done to make dr. mingw work for all threads? Thank you very much!

jrfonseca commented 2 years ago

the documentation for SetUnhandledExceptionFilter says that it works globally for all threads

Indeed SetUnhandledExceptionFilter reference does say that Issuing SetUnhandledExceptionFilter replaces the existing top-level exception filter for all existing and all future threads in the calling process.

But my memory is that it doesn't work like that. SetUnhandledExceptionFilter is what exchndl uses, so if it did replace the unhandled exception filter across all threads, then the symptoms @acidtonic reported at the beginning of this issue could not arise.

That said, it's possible my memory is wrong, and there's some external factor interfering with SetUnhandledExceptionFilter behavior in @acidtonic's case.

I googled, but couldn't find conclusive evidence either way.

Best way to know for sure would be to write a test.

One way or the other, SetUnhandledExceptionFilter is the only tool available I know. AddVectoredExceptionHandler is sure to be called on every exception, but there's no telling if it will be handled subsequently or not.

asmwarrior commented 2 years ago

Yes, hooking DLL_THREAD_ATTACH would be better than nothing.

If I remember correctly, debuggers such as GDB handles every DLL_THREAD_ATTACH event. So, I'm not sure how complex and difficulty does ExcHndl.dll need to do to support this? Just call the necessary SetUnhandledExceptionFilter() function call on each thread?

alvinhochun commented 2 years ago

I don't know why I made the comment re DLL_THREAD_ATTACH before, because now that I think about it, I recall seeing plenty of bug reports with crash backtraces that happened inside worker threads. This can only mean that exchndl does already handle multiple threads.

asmwarrior commented 2 years ago

I don't know why I made the comment re DLL_THREAD_ATTACH before, because now that I think about it, I recall seeing plenty of bug reports with crash backtraces that happened inside worker threads. This can only mean that exchndl does already handle multiple threads.

For my experiment here: https://github.com/jrfonseca/drmingw/issues/71#issuecomment-1203494112 it can catch the crash in a worker thread.

But in other cases, it can't catch the crash in the worker thread, see the first post in issue #71.

UniCd commented 2 months ago

is there any function that I could call manually to write the report file when catching a type of '...' exception, I need more stack information, because it was no use, i still don't know where the exception uccurred.

jrfonseca commented 1 month ago

is there any function that I could call manually to write the report file when catching a type of '...' exception, I need more stack information, because it was no use, i still don't know where the exception uccurred.

Yes, @UniCd , you could call DebugBreak. It should trigger the report generation.