diff --git a/base/src/core/include/rm_session_component.h b/base/src/core/include/rm_session_component.h
index e24f7aa7a0..5e6df370b4 100644
--- a/base/src/core/include/rm_session_component.h
+++ b/base/src/core/include/rm_session_component.h
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -258,8 +259,9 @@ namespace Genode {
};
- Tslab _client_slab; /* backing store for
- client structures */
+ typedef Synchronized_allocator > Client_slab_alloc;
+ Client_slab_alloc _client_slab; /* backing store for
+ client structures, synchronized */
Tslab _ref_slab; /* backing store for
region list */
Allocator_avl_tpl _map; /* region map for attach,
diff --git a/base/src/core/rm_session_component.cc b/base/src/core/rm_session_component.cc
index 340dd87eaa..d86c43ac66 100644
--- a/base/src/core/rm_session_component.cc
+++ b/base/src/core/rm_session_component.cc
@@ -683,9 +683,28 @@ Rm_session::State Rm_session_component::state()
void Rm_session_component::dissolve(Rm_client *cl)
{
- Lock::Guard lock_guard(_lock);
- _pager_ep->dissolve(cl);
- _clients.remove(cl);
+ {
+ Lock::Guard lock_guard(_lock);
+ _pager_ep->dissolve(cl);
+ _clients.remove(cl);
+ }
+
+ /*
+ * Rm_client is derived from Pager_object. If the Pager_object is also
+ * derived from Thread_base then the Rm_client object must be
+ * destructed without holding the rm_session_object lock. The native
+ * platform specific Thread_base implementation has to take care that
+ * all in-flight page handling requests are finished before
+ * destruction. (Either by waiting until the end of or by
+ * cancellation of the last in-flight request.
+ * This operation can also require taking the rm_session_object lock.
+ *
+ * Since _client_slab insertion/deletion also must be performed
+ * synchronized but can't be protected by the rm_session_object lock
+ * because of the described potential dead_lock situation, we have
+ * to use a synchronized allocator object to perform insertion and
+ * deletion of Rm_clients.
+ */
destroy(&_client_slab, cl);
}
@@ -728,13 +747,11 @@ Rm_session_component::~Rm_session_component()
}
/* remove all clients */
- while (Rm_client *cl = _client_slab.first_object()) {
- _pager_ep->dissolve(cl);
+ while (Rm_client *cl = _client_slab.raw()->first_object()) {
_lock.unlock();
cl->dissolve_from_faulting_rm_session();
+ this->dissolve(cl);
_lock.lock();
- _clients.remove(cl);
- destroy(&_client_slab, cl);
}
/* detach all regions */