[gvfs/sam/fuse-shutdown-on-error] fuse: Shutdown cleanly if an error occurs in vfs_init()



commit 9ac6a512bdb19e56b4fce62221340b3286e0a6ec
Author: Sam Thursfield <sam afuera me uk>
Date:   Sun Sep 29 14:12:36 2019 +0200

    fuse: Shutdown cleanly if an error occurs in vfs_init()
    
    I've been hitting the following problem:
    
      * start a temporary DBus session
      * run a program that calls into Gio
      * gvfsd is autostarted, and gvfsd-fuse is started
      * the program completes and the temporary bus shuts down
      * gvfsd-fuse is still starting, and it encounters an error inside the
        vfs_init() method like this:
    
          ** (process:6704): WARNING **: 12:55:27.957: Failed to connect to the D-BUS daemon: Could not 
connect: Connection refused (g-io-error-quark, 39)
    
      * gvfsd-fuse continues to the fuse main loop and never shuts down,
        despite the error.
    
    This leads to the temporary DBus session not shutting down as expected,
    and leads to dangling 'gvfs' fuse mounts.
    
    It seems like the problem is that the vfs_init() callback has no way
    of signalling failure. So this commit moves the shutdown code into an
    atexit() callback, which means we can safely call exit() from the
    vfs_init() constructor

 client/gvfsfusedaemon.c | 54 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 33 insertions(+), 21 deletions(-)
---
diff --git a/client/gvfsfusedaemon.c b/client/gvfsfusedaemon.c
index ff5641ae..bc9a6a2c 100644
--- a/client/gvfsfusedaemon.c
+++ b/client/gvfsfusedaemon.c
@@ -73,6 +73,9 @@ typedef struct {
   goffset   size;
 } FileHandle;
 
+static char           *mountpoint            = NULL;
+static struct fuse    *fuse                  = NULL;
+
 static GThread        *subthread             = NULL;
 static GMainLoop      *subthread_main_loop   = NULL;
 static GVfs           *gvfs                  = NULL;
@@ -2380,7 +2383,7 @@ register_fuse_cb (GVfsDBusMountTracker *proxy,
 
   if (! gvfs_dbus_mount_tracker_call_register_fuse_finish (proxy, res, &error))
     {
-      g_printerr ("register_fuse_cb: Error sending a message: %s (%s, %d)\n",
+      g_printerr ("gvfsd-fuse: register_fuse_cb: Error sending a message: %s (%s, %d)\n",
                   error->message, g_quark_to_string (error->domain), error->code);
       g_error_free (error);
     }
@@ -2413,10 +2416,10 @@ vfs_init (struct fuse_conn_info *conn)
   dbus_conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
   if (! dbus_conn)
     {
-      g_warning ("Failed to connect to the D-BUS daemon: %s (%s, %d)",
-                 error->message, g_quark_to_string (error->domain), error->code);
+      g_printerr ("gvfsd-fuse: Failed to connect to the D-BUS daemon: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
       g_error_free (error);
-      return NULL;
+      exit (1);
     }
   
   g_dbus_connection_set_exit_on_close (dbus_conn, FALSE);
@@ -2430,10 +2433,10 @@ vfs_init (struct fuse_conn_info *conn)
                                                   &error);
   if (proxy == NULL)
     {
-      g_printerr ("vfs_init(): Error creating proxy: %s (%s, %d)\n",
+      g_printerr ("gvfsd-fuse: vfs_init(): Error creating proxy: %s (%s, %d)\n",
                   error->message, g_quark_to_string (error->domain), error->code);
       g_error_free (error);
-      return NULL;
+      exit (1);
     }
 
   /* Allow the gvfs daemon autostart */
@@ -2544,13 +2547,31 @@ set_custom_signal_handlers (void (*handler)(int))
   sigaction (SIGTERM, &sa, NULL);
 }
 
+static void
+shutdown_fuse () {
+  struct fuse_chan *ch;
+  struct fuse_session *se;
+
+  if (fuse != NULL && mountpoint != NULL) {
+    /* Ignore new signals during exit procedure in order to terminate properly */
+    set_custom_signal_handlers (SIG_IGN);
+    fuse_remove_signal_handlers (se);
+
+    se = fuse_get_session (fuse);
+    ch = fuse_session_next_chan (se, NULL);
+
+    fuse_unmount (mountpoint, ch);
+    fuse_destroy (fuse);
+    free (mountpoint);
+
+    fuse = NULL;
+    mountpoint = NULL;
+  }
+}
+
 gint
 main (gint argc, gchar *argv [])
 {
-  struct fuse *fuse;
-  struct fuse_chan *ch;
-  struct fuse_session *se;
-  char *mountpoint;
   int multithreaded;
   int res;
 
@@ -2559,22 +2580,13 @@ main (gint argc, gchar *argv [])
   if (fuse == NULL)
     return 1;
 
+  atexit (shutdown_fuse);
+
   if (multithreaded)
     res = fuse_loop_mt (fuse);
   else
     res = fuse_loop (fuse);
 
-  se = fuse_get_session (fuse);
-  ch = fuse_session_next_chan (se, NULL);
-
-  /* Ignore new signals during exit procedure in order to terminate properly */
-  set_custom_signal_handlers (SIG_IGN);
-  fuse_remove_signal_handlers (se);
-
-  fuse_unmount (mountpoint, ch);
-  fuse_destroy (fuse);
-  free (mountpoint);
-
   if (res == -1)
     return 1;
 


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