New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Issue 19978 - D sometimes just crashes on exit with daemon threads #14907
Conversation
Thanks for your pull request and interest in making D better, @RazvanN7! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla references
|
Wouldn't this break if a thread is in a synchronized block on a mutex that is taken by the thread dtor? Ie. for instance if the dtor wants to close a connection but the thread is answering a request. |
53da442
to
23297e2
Compare
There are 2 mutexes involved here: one is the mutex that is used in syncronized blocks and the other is the mutex that is used to update information regarding the threads (like thread_list, context_list etc.). The mutex that I was referring to is the one for internal data structure modification. |
23297e2
to
3bb9e68
Compare
Right. I'm imagining code like
The hypothetical idea is that we're a daemon thread, the program exits, we want to run the thread dtor but without I don't know if this is a serious concern. Maybe the solution is to notice when a daemon thread is started and just disable all cleanup on exit? I don't think it can ever be done safely in the presence of daemon threads. |
Yes, that might be a problem (assuming you meant However, I don't think dropping support for module destructors in the presence of daemon threads is the way to go. Ideally, we could somehow reset all mutexes once the daemon threads are suspended and go on with destruction. |
Disclaimer: This PR is probably not the best solution and might suffer from some issues, however, I don't have any better ideas.
The problem seems to stem from the fact that daemon threads are not joined or stopped before memory is teared apart by the runtime. This leads to memory issues when the said daemon threads access memory that was freed. To fix this, I am suspending all threads before the cleanup process begins. Unfortunately, the only function that I've found to do that is suspendAll - which indiscriminately stops all threads and also acquires a lock on the global ThreadBase lock. This is problematic when the locks are freed because, typically, the lock is released when resumeAll is called. To fix this, I added an optional parameter to suspendAll (willNeverResume) so that the caller can stop the lock acquisition if the threads are suspended before terminating the process. I know that this is not ideal, but I am all ears for suggestions of better approaches; after all, I can't really find my way around druntime.
Note: This works on my machine but how do I test this in the testing framework?