-
-
Notifications
You must be signed in to change notification settings - Fork 243
fix(shutdown): Prevent race condition when GlobalObject destruction routine unlocks global mutex #8652
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
base: master
Are you sure you want to change the base?
fix(shutdown): Prevent race condition when GlobalObject destruction routine unlocks global mutex #8652
Conversation
…ine unlocks global mutex Unlocking global mutex in GlobalObject destruction routine made it possible for a new attachment to slip in, so it will be creating new GlobalObject and using it, while destroying routine still in action. This can lead to an undefined state of the global objects, such as shared memory, where one thread is actively using it while another thread is destroying it.
Found issue with current fix using bool: If we set |
Looks like instead of using global flag, common for all databases, we need per-database flag. Raw idea: remove When concurrent creator founds that constant, it should wait for no-entry in hash table before attempt to create new instance. Instead of fixed constant, consider to use some sync object (mutex? special instance of GlobalObjectHolder ?) that could be used to wait for, instead of poll + sleep in a loop. |
Looks like as a pattern for mutex + condition variable that waits while g_shuttingDown is true and is notified when it's false. |
…routine for GlobalObjectHolder
I reimplemented the fix by adding a mutex to |
Unlocking global mutex in GlobalObject destruction routine made it possible for a new attachment to slip in, so it will create new GlobalObject and use it, while destroying routine still in action. This can lead to an undefined state of the global objects, such as shared memory, where one thread is actively using it while another thread is destroying it.
v5 is also affected.
Examples of this race condition:
Example 1 - Deadlock.
Thread 1 is holding
sh_mem_mutex
(atJrd::LockManager::~LockManager
), and waiting for flock oninitFile
;Thread 2 is holding flock on
initFile
(atFirebird::SharedMemoryBase::SharedMemoryBase
), and waiting forsh_mem_mutex
;Trace
Example 2 - Crash.
Thread 1 - New attachment trying to use deleted shared file for
LockManager
.Thread 2 - Complete
JRD_shutdown_database
routine, clear GlobalObject, and leave without any trace...Trace