summaryrefslogtreecommitdiff
path: root/src/syncevo/ForkExec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/syncevo/ForkExec.cpp')
-rw-r--r--src/syncevo/ForkExec.cpp42
1 files changed, 35 insertions, 7 deletions
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