diff options
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/src/Ice/Connection.cpp | 42 |
1 files changed, 27 insertions, 15 deletions
diff --git a/cpp/src/Ice/Connection.cpp b/cpp/src/Ice/Connection.cpp index 10194a8adbc..aebac1916e6 100644 --- a/cpp/src/Ice/Connection.cpp +++ b/cpp/src/Ice/Connection.cpp @@ -1034,24 +1034,36 @@ IceInternal::Connection::setAdapter(const ObjectAdapterPtr& adapter) // Before we set an adapter (or reset it) we wait until the // dispatch count with any old adapter is zero. // - while(_dispatchCount > 0) - { - wait(); - } - + // A deadlock can occur if we wait while an operation is + // outstanding on this adapter that holds a lock while + // calling this function (e.g., __getDelegate). // - // We never change the thread pool with which we were initially - // registered, even if we add or remove an object adapter. + // In order to avoid such a deadlock, we only wait if the new + // adapter is different than the current one. // - - _adapter = adapter; - if(_adapter) - { - _servantManager = dynamic_cast<ObjectAdapterI*>(_adapter.get())->getServantManager(); - } - else + // TODO: Verify that this fix solves all cases. + // + if(_adapter.get() != adapter.get()) { - _servantManager = 0; + while(_dispatchCount > 0) + { + wait(); + } + + // + // We never change the thread pool with which we were initially + // registered, even if we add or remove an object adapter. + // + + _adapter = adapter; + if(_adapter) + { + _servantManager = dynamic_cast<ObjectAdapterI*>(_adapter.get())->getServantManager(); + } + else + { + _servantManager = 0; + } } } |