Merge branch 'master' of git+ssh://g-rjones@et.redhat.com/git/virt-hostinfo
[virt-hostinfo.git] / hostinfod / main.c
index fa835bb..e9ca8ae 100644 (file)
@@ -51,6 +51,7 @@ static void do_reread_socket_dir (void);
 static struct guest_description *guest_added (const char *sock_path, const char *name);
 static void guest_removed (struct guest_description *);
 static void guest_event (const apr_pollfd_t *, void *);
+static void modify_pollfd_reqevents (struct guest_description *, apr_int16_t);
 
 const char *conf_file = DEFAULT_CONF_FILE;
 char *socket_dir = NULL;
@@ -96,6 +97,14 @@ usage (void)
          DEFAULT_CONF_FILE);
 }
 
+void
+initialize (void)
+{
+  apr_initialize ();
+  apr_pool_create (&pool, NULL);
+  init_syslog ();
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -111,13 +120,16 @@ main (int argc, char *argv[])
   int c;
   const char *optarg;
 
-  apr_initialize ();
-  apr_pool_create (&pool, NULL);
+  /* REGISTER_COMMAND macro should have caused this to be
+   * initialized.  If it's not, then something is badly wrong ...
+   */
+  if (!pool) {
+    error ("internal error: daemon not initialized - no commands registered");
+    exit (1);
+  }
 
   apr_getopt_init (&opt, pool, argc, argv);
 
-  init_syslog ();
-
   socket_dir = apr_pstrdup (pool, DEFAULT_SOCKET_DIR);
   guests_file = apr_pstrdup (pool, DEFAULT_GUESTS_FILE);
 
@@ -169,7 +181,7 @@ main (int argc, char *argv[])
     paprerror (r, "apr_pollset_create");
     exit (1);
   }
-  apr_socket_t *tsock;
+  apr_socket_t *tsock = NULL;
   r = apr_os_sock_put (&tsock, &sockets_inotify_fd, pool);
   if (r != APR_SUCCESS) {
     paprerror (r, "apr_os_sock_put");
@@ -229,6 +241,8 @@ main_loop (void)
     }
 
     /* Poll. */
+    numdescs = 0;
+    descs = NULL;
     r = apr_pollset_poll (set, -1, &numdescs, &descs);
     if (r != APR_SUCCESS) {
       paprerror (r, "apr_pollset_poll");
@@ -370,7 +384,7 @@ guest_added (const char *sock_path, const char *name)
   int r;
   unsigned retries = 0, tns;
   enum guest_state state;
-  apr_pool_t *guest_pool;
+  apr_pool_t *guest_pool = NULL;
   struct sockaddr_un addr;
   struct timespec ts;
 
@@ -491,7 +505,7 @@ guest_removed (struct guest_description *hval)
   /* Unregister the socket from the pollset. */
   r = apr_pollset_remove (set, &hval->pollfd);
   if (r != APR_SUCCESS)
-    paprerror (r, "apr_pollset_remove for %s", hval->name);
+    paprerror (r, "%s: apr_pollset_remove", hval->name);
 
   if (close (hval->sock) == -1)
     pwarningf ("close: %s", hval->sock_path);
@@ -692,16 +706,40 @@ guest_event (const apr_pollfd_t *pollfd, void *hvalv)
    */
   switch (hval->state) {
   case guest_state_connecting:
-    hval->pollfd.reqevents = APR_POLLOUT;
+    modify_pollfd_reqevents (hval, APR_POLLOUT);
     break;
   case guest_state_request:
-    hval->pollfd.reqevents = APR_POLLIN;
+    modify_pollfd_reqevents (hval, APR_POLLIN);
     break;
   case guest_state_reply:
-    hval->pollfd.reqevents = APR_POLLOUT;
+    modify_pollfd_reqevents (hval, APR_POLLOUT);
     break;
   case guest_state_dead:
-    hval->pollfd.reqevents = 0;
+    modify_pollfd_reqevents (hval, 0);
     break;
   }
 }
+
+/* It turns out you can't just update the pollfd->reqevents
+ * field.  Instead you have to remove the pollfd and reregister
+ * it in the pollset.
+ */
+static void
+modify_pollfd_reqevents (struct guest_description *hval,
+                        apr_int16_t new_reqevents)
+{
+  apr_status_t r;
+
+  if (hval->pollfd.reqevents != new_reqevents) {
+    r = apr_pollset_remove (set, &hval->pollfd);
+    if (r != APR_SUCCESS) {
+      paprerror (r, "%s: apr_pollset_remove", hval->name);
+      return;
+    }
+
+    hval->pollfd.reqevents = new_reqevents;
+    r = apr_pollset_add (set, &hval->pollfd);
+    if (r != APR_SUCCESS)
+      paprerror (r, "%s: apr_pollset_add", hval->name);
+  }
+}