diff options
-rw-r--r-- | src/dbus/server/session-helper.cpp | 2 | ||||
-rw-r--r-- | src/dbus/server/session.cpp | 9 | ||||
-rw-r--r-- | src/syncevo/ForkExec.cpp | 42 | ||||
-rw-r--r-- | src/syncevo/ForkExec.h | 8 |
4 files changed, 49 insertions, 12 deletions
diff --git a/src/dbus/server/session-helper.cpp b/src/dbus/server/session-helper.cpp index 0df0004b..0ae993d9 100644 --- a/src/dbus/server/session-helper.cpp +++ b/src/dbus/server/session-helper.cpp @@ -107,7 +107,7 @@ SessionHelper::SessionHelper(GMainLoop *loop, const boost::shared_ptr<ForkExecChild> &forkexec, const boost::shared_ptr<LogRedirect> &parentLogger) : GDBusCXX::DBusObjectHelper(conn, - SessionCommon::HELPER_PATH, + std::string(SessionCommon::HELPER_PATH) + "/" + forkexec->getInstance(), SessionCommon::HELPER_IFACE, GDBusCXX::DBusObjectHelper::Callback_t(), // we don't care about a callback per message true), // direct connection, close it when done diff --git a/src/dbus/server/session.cpp b/src/dbus/server/session.cpp index acae499c..134c8e17 100644 --- a/src/dbus/server/session.cpp +++ b/src/dbus/server/session.cpp @@ -43,9 +43,9 @@ SE_BEGIN_CXX class SessionProxy : public GDBusCXX::DBusRemoteObject { public: - SessionProxy(const GDBusCXX::DBusConnectionPtr &conn) : + SessionProxy(const GDBusCXX::DBusConnectionPtr &conn, const std::string &instance) : GDBusCXX::DBusRemoteObject(conn.get(), - SessionCommon::HELPER_PATH, + std::string(SessionCommon::HELPER_PATH) + "/" + instance, SessionCommon::HELPER_IFACE, SessionCommon::HELPER_DESTINATION, true), // This is a one-to-one connection. Close it. @@ -874,8 +874,9 @@ void Session::onConnect(const GDBusCXX::DBusConnectionPtr &conn) throw () { PushLogger<Logger> guard(m_me); try { - SE_LOG_DEBUG(NULL, "helper has connected"); - m_helper.reset(new SessionProxy(conn)); + std::string instance = m_forkExecParent->getInstance(); + SE_LOG_DEBUG(NULL, "helper %s has connected", instance.c_str()); + m_helper.reset(new SessionProxy(conn, instance)); // Activate signal watch on helper signals. m_helper->m_syncProgress.activate(boost::bind(&Session::syncProgress, this, _1, _2, _3, _4)); diff --git a/src/syncevo/ForkExec.cpp b/src/syncevo/ForkExec.cpp index 46cd1d67..14ad4a6b 100644 --- a/src/syncevo/ForkExec.cpp +++ b/src/syncevo/ForkExec.cpp @@ -19,15 +19,18 @@ #include "ForkExec.h" #include <syncevo/LogRedirect.h> +#include <syncevo/ThreadSupport.h> #if defined(HAVE_GLIB) #include <pcrecpp.h> +#include <ctype.h> #include "test.h" SE_BEGIN_CXX static const std::string ForkExecEnvVar("SYNCEVOLUTION_FORK_EXEC="); +static const std::string ForkExecInstanceEnvVar("SYNCEVOLUTION_FORK_EXEC_INSTANCE="); #ifndef GDBUS_CXX_HAVE_DISCONNECT // internal D-Bus API: only used to monitor parent by having one method call pending @@ -44,18 +47,34 @@ static const std::string FORKEXEC_PARENT_DESTINATION = "direct.peer"; // doesn't class ForkExecParentDBusAPI : public GDBusCXX::DBusObjectHelper { public: - ForkExecParentDBusAPI(const GDBusCXX::DBusConnectionPtr &conn) : + /** + * @param instance a unique string to distinguish multiple different ForkExecParent + * instances; necessary because otherwise GIO GDBus may route messages from + * one connection to older instances on other connections + */ + ForkExecParentDBusAPI(const GDBusCXX::DBusConnectionPtr &conn, const std::string &instance) : GDBusCXX::DBusObjectHelper(conn, - FORKEXEC_PARENT_PATH, + FORKEXEC_PARENT_PATH + "/" + instance, FORKEXEC_PARENT_IFACE) { add(this, &ForkExecParentDBusAPI::watch, "Watch"); activate(); } + ~ForkExecParentDBusAPI() + { + SE_LOG_DEBUG(NULL, "ForkExecParentDBusAPI %s: destroying with %ld active watches", + getPath(), + (long)m_watches.size()); + } + + bool hasWatches() const { return !m_watches.empty(); } + private: void watch(const boost::shared_ptr< GDBusCXX::Result0> &result) { + SE_LOG_DEBUG(NULL, "ForkExecParentDBusAPI %s: received 'Watch' method call from child", + getPath()); m_watches.push_back(result); } std::list< boost::shared_ptr< GDBusCXX::Result0> > m_watches; @@ -66,6 +85,9 @@ ForkExec::ForkExec() { } +static Mutex ForkExecMutex; +static unsigned int ForkExecCount; + ForkExecParent::ForkExecParent(const std::string &helper) : m_helper(helper), m_childPid(0), @@ -81,6 +103,9 @@ ForkExecParent::ForkExecParent(const std::string &helper) : m_errID(0), m_watchChild(NULL) { + Mutex::Guard guard = ForkExecMutex.lock(); + ForkExecCount++; + m_instance = StringPrintf("forkexec%u", ForkExecCount); } boost::shared_ptr<ForkExecParent> ForkExecParent::create(const std::string &helper) @@ -182,13 +207,15 @@ void ForkExecParent::start() for (char **env = environ; *env; env++) { - if (!boost::starts_with(*env, ForkExecEnvVar)) { + if (!boost::starts_with(*env, ForkExecEnvVar) && + !boost::starts_with(*env, ForkExecInstanceEnvVar)) { m_envStrings.push_back(*env); } } // pass D-Bus address via env variable m_envStrings.push_back(ForkExecEnvVar + m_server->getAddress()); + m_envStrings.push_back(ForkExecInstanceEnvVar + getInstance()); m_env.reset(AllocStringArray(m_envStrings)); SE_LOG_DEBUG(NULL, "ForkExecParent: running %s with D-Bus address %s", @@ -375,7 +402,7 @@ void ForkExecParent::newClientConnection(GDBusCXX::DBusConnectionPtr &conn) thro m_helper.c_str()); m_hasConnected = true; #ifndef GDBUS_CXX_HAVE_DISCONNECT - m_api.reset(new ForkExecParentDBusAPI(conn)); + m_api.reset(new ForkExecParentDBusAPI(conn, getInstance())); #endif m_onConnect(conn); } catch (...) { @@ -442,6 +469,7 @@ void ForkExecParent::kill() ForkExecChild::ForkExecChild() : m_state(IDLE) { + m_instance = getEnv(ForkExecInstanceEnvVar.substr(0, ForkExecInstanceEnvVar.size() - 1).c_str(), ""); } boost::shared_ptr<ForkExecChild> ForkExecChild::create() @@ -480,16 +508,16 @@ void ForkExecChild::connect() class Parent : public GDBusCXX::DBusRemoteObject { public: - Parent(const GDBusCXX::DBusConnectionPtr &conn) : + Parent(const GDBusCXX::DBusConnectionPtr &conn, const std::string &instance) : GDBusCXX::DBusRemoteObject(conn, - FORKEXEC_PARENT_PATH, + FORKEXEC_PARENT_PATH + "/" + instance, FORKEXEC_PARENT_IFACE, FORKEXEC_PARENT_DESTINATION), m_watch(*this, "Watch") {} GDBusCXX::DBusClientCall0 m_watch; - } parent(conn); + } parent(conn, getInstance()); parent.m_watch.start(boost::bind(&ForkExecChild::connectionLost, this)); #endif diff --git a/src/syncevo/ForkExec.h b/src/syncevo/ForkExec.h index 5de1848c..e460e59d 100644 --- a/src/syncevo/ForkExec.h +++ b/src/syncevo/ForkExec.h @@ -100,8 +100,16 @@ class ForkExec : private boost::noncopyable { typedef boost::signals2::signal<void (SyncMLStatus, const std::string &)> OnFailure; OnFailure m_onFailure; + /** + * A unique string for the ForkExecParent/Child pair which can be used + * as D-Bus path component. + */ + std::string getInstance() const { return m_instance; } + protected: ForkExec(); + + std::string m_instance; }; /** |