syncevo-dbus-server: fix for handling of active session

The logic for creating a shared_ptr for the active session
was flawed: it assumed that the session must be owned by
a client, which is not true if some other entity (like
a Connection) owns it.

As a result of this flaw, DBusServer::m_syncSession wasn't
set when running a sync via the Connection API, which
crashed when the Connection destructed itself and the
session while some of the session code was still active.

Fixed by keeping both a plain pointer (for the case when
the weak_ptr doesn't provide it anymore while shutting
itself down) and a weak_ptr (which avoids searching for
the shared_ptr).
This commit is contained in:
Patrick Ohly 2009-09-17 21:03:53 +02:00
parent 18a0d2ad3d
commit 88f35083a5
1 changed files with 13 additions and 10 deletions

View File

@ -110,12 +110,17 @@ class DBusServer : public DBusObjectHelper
* only one session may make such modifications at a time. A
* plain pointer which is reset by the session's deconstructor.
*
* A weak pointer did not work because it does not provide access
* A weak pointer alone did not work because it does not provide access
* to the underlying pointer after the last corresponding shared
* pointer is gone (which triggers the deconstructing of the session).
*/
Session *m_activeSession;
/**
* The weak pointer that corresponds to m_activeSession.
*/
boost::weak_ptr<Session> m_activeSessionRef;
/**
* The running sync session. Having a separate reference to it
* ensures that the object won't go away prematurely, even if all
@ -1261,17 +1266,13 @@ void DBusServer::run()
if (m_activeSession &&
m_activeSession->readyToRun()) {
// this session must be owned by someone, otherwise
// it would not be set as active session => find
// that shared pointer and get a reference
boost::shared_ptr<Session> session;
BOOST_FOREACH(const Clients_t::value_type &client_entry,
m_clients) {
session = boost::static_pointer_cast<Session, Resource>(client_entry.second->findResource(m_activeSession));
if (session) {
break;
}
// it would not be set as active session
boost::shared_ptr<Session> session = m_activeSessionRef.lock();
if (!session) {
throw runtime_error("internal error: session no longer available");
}
try {
// ensure that the session doesn't go away
m_syncSession.swap(session);
m_activeSession->run();
} catch (const std::exception &ex) {
@ -1362,6 +1363,7 @@ void DBusServer::dequeue(Session *session)
session->setActive(false);
sessionChanged(session->getPath(), false);
m_activeSession = NULL;
m_activeSessionRef.reset();
checkQueue();
return;
}
@ -1380,6 +1382,7 @@ void DBusServer::checkQueue()
if (session) {
// activate the session
m_activeSession = session.get();
m_activeSessionRef = session;
session->setActive(true);
sessionChanged(session->getPath(), true);
return;