Separate the service loop termination process from the destructor 58/114458/3
authorMu-Woong Lee <muwoong.lee@samsung.com>
Mon, 13 Feb 2017 10:42:43 +0000 (19:42 +0900)
committerMu-Woong Lee <muwoong.lee@samsung.com>
Mon, 20 Feb 2017 06:01:26 +0000 (15:01 +0900)
Change-Id: I9fbda1dc473d550f773ffd09ba68e494c67bc1c9
Signed-off-by: Mu-Woong Lee <muwoong.lee@samsung.com>
include/DBusService.h
src/server/DBusService.cpp

index 2de9031..9dbf54c 100644 (file)
@@ -35,6 +35,8 @@ namespace ctx {
 
                bool start();
 
+               void stop();
+
                // If the GVariant 'param' is floating, it is consumed.
                void publish(const std::string& busName, const std::string& signalName, GVariant* param);
 
@@ -43,10 +45,13 @@ namespace ctx {
        protected:
                DBusService(GDBusConnection* conn, const char* serviceName, const char* methodSpecs);
 
-               virtual void prepare() = 0;
-               virtual ClientProxy* createProxy(const std::string& busName) = 0;
+               virtual bool prepare() = 0;
+
+               virtual void cleanup() = 0;
 
-               virtual void onUserActivated(uid_t uid);
+               virtual void onUserActivated(uid_t uid) = 0;
+
+               virtual ClientProxy* createProxy(const std::string& busName) = 0;
 
        private:
                static gpointer __threadFunc(gpointer data);
@@ -63,6 +68,8 @@ namespace ctx {
                                const gchar* path, const gchar* iface, const gchar* name,
                                GVariant* param, gpointer userData);
 
+               static gboolean __stopMainLoop(gpointer data);
+
                void __onMethodCalled(const std::string& sender,
                                const std::string& name, GVariant* param, GDBusMethodInvocation* invocation);
 
index 052498d..1b440ae 100644 (file)
@@ -42,19 +42,6 @@ DBusService::DBusService(GDBusConnection* conn, const char* serviceName, const c
 
 DBusService::~DBusService()
 {
-#ifndef SINGLE_THREADING
-       if (__mainLoop && g_main_loop_is_running(__mainLoop)) {
-               _I(PURPLE("Stopping the mainloop of '%s'"), __serviceName);
-               g_main_loop_quit(__mainLoop);
-       }
-
-       if (__gthread) {
-               _I("Joining the thread of '%s'", __serviceName);
-               g_thread_join(__gthread);
-       }
-#else
-       __release();
-#endif
 }
 
 GDBusConnection* DBusService::getConnection()
@@ -72,12 +59,43 @@ bool DBusService::start()
 #else
        _I(CYAN("'%s' runs on the default main loop"), __serviceName);
        IF_FAIL_RETURN(__init(), false);
-       prepare();
 #endif
 
        return true;
 }
 
+void DBusService::stop()
+{
+#ifndef SINGLE_THREADING
+       if (__mainLoop && g_main_loop_is_running(__mainLoop)) {
+               GSource *gSrc = g_idle_source_new();
+               if (gSrc) {
+                       // Tries to stop the main loop within its thread.
+                       // In this way, already scheduled idle tasks are not discarded.
+                       g_source_set_callback(gSrc, __stopMainLoop, this, NULL);
+                       g_source_attach(gSrc, __mainContext);
+               } else {
+                       __stopMainLoop(this);
+               }
+       }
+
+       if (__gthread) {
+               _I("Joining the thread of '%s'", __serviceName);
+               g_thread_join(__gthread);
+       }
+#else
+       __release();
+#endif
+}
+
+gboolean DBusService::__stopMainLoop(gpointer data)
+{
+       DBusService* svc = static_cast<DBusService*>(data);
+       _I(PURPLE("Stopping '%s'"), svc->__serviceName);
+       g_main_loop_quit(svc->__mainLoop);
+       return G_SOURCE_REMOVE;
+}
+
 void DBusService::publish(const std::string& busName, const std::string& signalName, GVariant* param)
 {
        GError* gerr = NULL;
@@ -87,10 +105,6 @@ void DBusService::publish(const std::string& busName, const std::string& signalN
        HANDLE_GERROR(gerr);
 }
 
-void DBusService::onUserActivated(uid_t uid)
-{
-}
-
 uid_t DBusService::getActiveUser()
 {
        if (__activeUid == 0) {
@@ -118,8 +132,6 @@ void DBusService::__run()
                return;
        }
 
-       prepare();
-
        _I(CYAN("Starting '%s'"), __serviceName);
        g_main_loop_run(__mainLoop);
 
@@ -160,11 +172,13 @@ bool DBusService::__init()
                        NULL, "org.freedesktop.login1.Manager", "UserNew", NULL,
                        NULL, G_DBUS_SIGNAL_FLAGS_NONE, __onUserNew, this, NULL);
 
-       return true;
+       return prepare();
 }
 
 void DBusService::__release()
 {
+       _D("Releasing '%s'", __serviceName);
+
        for (auto iter = __proxies.begin(); iter != __proxies.end(); ++iter) {
                iter->second.proxy->onDisconnected();
                delete iter->second.proxy;
@@ -172,6 +186,8 @@ void DBusService::__release()
 
        __proxies.clear();
 
+       cleanup();
+
        if (__userNewSignalId > 0)
                g_dbus_connection_signal_unsubscribe(__connection, __userNewSignalId);
 
@@ -181,13 +197,11 @@ void DBusService::__release()
        if (__nodeInfo)
                g_dbus_node_info_unref(__nodeInfo);
 
-#ifndef SINGLE_THREADING
        if (__mainLoop)
                g_main_loop_unref(__mainLoop);
 
        if (__mainContext)
                g_main_context_unref(__mainContext);
-#endif
 }
 
 void DBusService::__onUserNew(GDBusConnection* conn, const gchar* sender,