[wing/wip/nacho/service] service: allow to run a service without passing a GApplication



commit 436cf20e22aeb51236bea290fbc25f8cea778bd0
Author: Ignacio Casal Quinteiro <qignacio amazon com>
Date:   Tue Jun 20 13:01:50 2017 +0200

    service: allow to run a service without passing a GApplication
    
    There may be use cases where a GApplication is not required.

 wing/wingservice.c |   95 +++++++++++++++++++++++++++++++++++++++------------
 wing/wingservice.h |   31 ++++++++++-------
 2 files changed, 90 insertions(+), 36 deletions(-)
---
diff --git a/wing/wingservice.c b/wing/wingservice.c
index a820d57..06bf510 100644
--- a/wing/wingservice.c
+++ b/wing/wingservice.c
@@ -41,6 +41,7 @@ typedef struct _WingServicePrivate
   SERVICE_STATUS status;
   SERVICE_STATUS_HANDLE status_handle;
   gboolean notify_service_stop;
+  gboolean must_quit_now;
 } WingServicePrivate;
 
 typedef struct
@@ -264,8 +265,11 @@ on_handle_local_options (GApplication *application,
   if (ret == -1)
     {
       priv->notify_service_stop = TRUE;
-      g_application_hold (priv->application);
+      if (priv->application != NULL)
+        g_application_hold (priv->application);
     }
+  else
+    priv->must_quit_now = TRUE;
 
   return ret;
 }
@@ -275,7 +279,6 @@ wing_service_constructed (GObject *object)
 {
   WingService *service = WING_SERVICE (object);
   WingServicePrivate *priv;
-  GOptionGroup *option_group;
 
   priv = wing_service_get_instance_private (service);
 
@@ -290,19 +293,6 @@ wing_service_constructed (GObject *object)
 
   priv->status.dwControlsAccepted = service_flags (service);
 
-  /* service options */
-  option_group = g_option_group_new ("wing",
-                                     "Windows Service Options",
-                                     "Show the Windows Service Options",
-                                     NULL, NULL);
-  g_option_group_add_entries (option_group, entries);
-  g_application_add_option_group (priv->application, option_group);
-
-  g_signal_connect (priv->application,
-                    "handle-local-options",
-                    G_CALLBACK (on_handle_local_options),
-                    service);
-
   G_OBJECT_CLASS (wing_service_parent_class)->constructed (object);
 }
 
@@ -410,8 +400,20 @@ wing_service_init (WingService *service)
 WingService *
 wing_service_new (const gchar      *name,
                   const gchar      *description,
-                  WingServiceFlags  flags,
-                  GApplication     *application)
+                  WingServiceFlags  flags)
+{
+  return g_object_new (WING_TYPE_SERVICE,
+                       "name", name,
+                       "description", description,
+                       "flags", flags,
+                       NULL);
+}
+
+WingService *
+wing_service_new_with_application (const gchar      *name,
+                                   const gchar      *description,
+                                   WingServiceFlags  flags,
+                                   GApplication     *application)
 {
   return g_object_new (WING_TYPE_SERVICE,
                        "name", name,
@@ -524,8 +526,13 @@ on_control_handler_idle (gpointer user_data)
     case SERVICE_CONTROL_STOP:
     case SERVICE_CONTROL_SHUTDOWN:
       g_signal_emit (G_OBJECT (service), signals[STOP], 0);
-      g_application_release (priv->application);
-      g_application_quit (priv->application);
+      if (priv->application)
+        {
+          g_application_release (priv->application);
+          g_application_quit (priv->application);
+        }
+      else
+        priv->must_quit_now = TRUE;
       break;
     case SERVICE_CONTROL_PAUSE:
       g_signal_emit (G_OBJECT (service), signals[PAUSE], 0);
@@ -667,14 +674,15 @@ wing_service_run (WingService  *service,
                   int           argc,
                   char        **argv)
 {
-  WingServicePrivate *priv;
+  WingServicePrivate *priv = wing_service_get_instance_private (service);
   int status = 0;
   gchar *thread_name;
   gint64 end_time;
+  GOptionGroup *option_group;
 
   g_return_val_if_fail (WING_IS_SERVICE (service), 1);
-
-  priv = wing_service_get_instance_private (service);
+  g_return_val_if_fail (argc == 0 || argv != NULL, 1);
+  g_return_val_if_fail (!priv->must_quit_now, 1);
 
   g_mutex_lock (&priv->start_mutex);
 
@@ -695,7 +703,48 @@ wing_service_run (WingService  *service,
 
   g_mutex_unlock (&priv->start_mutex);
 
-  status = g_application_run (priv->application, argc, argv);
+  /* service options */
+  option_group = g_option_group_new ("wing",
+                                     "Windows Service Options",
+                                     "Show the Windows Service Options",
+                                     NULL, NULL);
+  g_option_group_add_entries (option_group, entries);
+
+  if (priv->application != NULL)
+    {
+      status = g_application_run (priv->application, argc, argv);
+      g_application_add_option_group (priv->application, option_group);
+
+      g_signal_connect (priv->application,
+                        "handle-local-options",
+                        G_CALLBACK (on_handle_local_options),
+                        service);
+    }
+  else
+    {
+      GMainContext *context;
+      gboolean acquired_context;
+      GOptionContext *option_context;
+      GError *error = NULL;
+
+      context = g_main_context_default ();
+      acquired_context = g_main_context_acquire (context);
+      g_return_val_if_fail (acquired_context, 0);
+
+      option_context = g_option_context_new (NULL);
+      if (!g_option_context_parse (option_context, &argc, &argv, &error))
+        {
+          g_warning ("Could not parse the wing options: %s", error->message);
+          g_error_free (error);
+          return 1;
+        }
+
+      if (!priv->must_quit_now)
+        while (g_main_context_iteration (context, TRUE))
+          ;
+
+      g_main_context_release (context);
+    }
 
   if (priv->notify_service_stop)
     set_service_status (service, SERVICE_STOPPED);
diff --git a/wing/wingservice.h b/wing/wingservice.h
index 60967be..0b26ca7 100644
--- a/wing/wingservice.h
+++ b/wing/wingservice.h
@@ -71,33 +71,38 @@ typedef enum
 } WingServiceFlags;
 
 WING_AVAILABLE_IN_ALL
-GType                  wing_service_get_type        (void) G_GNUC_CONST;
+GType                  wing_service_get_type               (void) G_GNUC_CONST;
 
 WING_AVAILABLE_IN_ALL
-WingService           *wing_service_new             (const gchar      *name,
-                                                     const gchar      *description,
-                                                     WingServiceFlags  flags,
-                                                     GApplication     *application);
+WingService           *wing_service_new                    (const gchar      *name,
+                                                            const gchar      *description,
+                                                            WingServiceFlags  flags);
 
 WING_AVAILABLE_IN_ALL
-WingService           *wing_service_get_default     (void);
+WingService           *wing_service_new_with_application   (const gchar      *name,
+                                                            const gchar      *description,
+                                                            WingServiceFlags  flags,
+                                                            GApplication     *application);
 
 WING_AVAILABLE_IN_ALL
-void                   wing_service_set_default     (WingService *service);
+WingService           *wing_service_get_default            (void);
 
 WING_AVAILABLE_IN_ALL
-const gchar           *wing_service_get_name        (WingService *service);
+void                   wing_service_set_default            (WingService *service);
 
 WING_AVAILABLE_IN_ALL
-const gchar           *wing_service_get_description (WingService *service);
+const gchar           *wing_service_get_name               (WingService *service);
 
 WING_AVAILABLE_IN_ALL
-WingServiceFlags       wing_service_get_flags       (WingService *service);
+const gchar           *wing_service_get_description        (WingService *service);
 
 WING_AVAILABLE_IN_ALL
-int                    wing_service_run             (WingService  *service,
-                                                     int           argc,
-                                                     char        **argv);
+WingServiceFlags       wing_service_get_flags              (WingService *service);
+
+WING_AVAILABLE_IN_ALL
+int                    wing_service_run                    (WingService  *service,
+                                                            int           argc,
+                                                            char        **argv);
 
 G_END_DECLS
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]