diff options
author | Asen Kirov <akirov@luxoft.com> | 2015-10-22 15:42:18 +0300 |
---|---|---|
committer | Asen Kirov <akirov@luxoft.com> | 2015-10-22 15:42:18 +0300 |
commit | 2b76d0ccac3ceb0e6568fef95bd874b7d7a598d7 (patch) | |
tree | dd72d81bdf424096a696437385298f4dae36f04c /src/components/utils/include | |
parent | cee517d5ff7f7aeecef453460ebeef79bdcef4e1 (diff) | |
download | sdl_core-2b76d0ccac3ceb0e6568fef95bd874b7d7a598d7.tar.gz |
Fix race condition in Singleton and Application Manager failure to stop
When SDL is started, but the HMI is not, and we try to register a mobile
app (RegisterAppInterfaceRequest), then in this situation SDL can't be
stopped with ctrl+C - it enters in an endless cycle.
The reason for the problem is that we can't delete the AM, because the
RequestController thread of AM is still running (waiting in a cycle for
the HMI to respond). Also a second AM is created, because in the
Singleton we set to 0 the instance pointer before deleting it and
someone calls instance() before destroy() finishes, because there is no
common lock. The separate locks create a race condition.
The fix is to use a single mutex for the Singleton methods, introduce a
is_stopping_ flag in AM, set it to true in AM's Stop() method, and
also destroy RequestController's thread pool there.
Then check stop flag in RegisterAppInterfaceRequest::Run() and exit the
HMI waiting cycle there.
Diffstat (limited to 'src/components/utils/include')
-rw-r--r-- | src/components/utils/include/utils/singleton.h | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/src/components/utils/include/utils/singleton.h b/src/components/utils/include/utils/singleton.h index 41face4f2f..fff7294d1c 100644 --- a/src/components/utils/include/utils/singleton.h +++ b/src/components/utils/include/utils/singleton.h @@ -111,18 +111,24 @@ class Singleton { static T** instance_pointer(); static Deleter* deleter(); + + static sync_primitives::Lock lock_; }; + +template<typename T, class Deleter> +sync_primitives::Lock Singleton<T, Deleter>::lock_; + + template<typename T, class Deleter> T* Singleton<T, Deleter>::instance() { - static sync_primitives::Lock lock; T* local_instance; atomic_pointer_assign(local_instance, *instance_pointer()); memory_barrier(); if (!local_instance) { - lock.Acquire(); + lock_.Acquire(); local_instance = *instance_pointer(); if (!local_instance) { local_instance = new T(); @@ -130,7 +136,7 @@ T* Singleton<T, Deleter>::instance() { atomic_pointer_assign(*instance_pointer(), local_instance); deleter()->grab(local_instance); } - lock.Release(); + lock_.Release(); } return local_instance; @@ -138,14 +144,13 @@ T* Singleton<T, Deleter>::instance() { template<typename T, class Deleter> void Singleton<T, Deleter>::destroy() { - static sync_primitives::Lock lock; T* local_instance; atomic_pointer_assign(local_instance, *instance_pointer()); memory_barrier(); if (local_instance) { - lock.Acquire(); + lock_.Acquire(); local_instance = *instance_pointer(); if (local_instance) { atomic_pointer_assign(*instance_pointer(), 0); @@ -153,7 +158,7 @@ void Singleton<T, Deleter>::destroy() { delete local_instance; deleter()->grab(0); } - lock.Release(); + lock_.Release(); } } |