summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam@afuera.me.uk>2019-09-29 14:12:36 +0200
committerSam Thursfield <sam@afuera.me.uk>2019-09-29 14:12:36 +0200
commit9ac6a512bdb19e56b4fce62221340b3286e0a6ec (patch)
tree107b896aefa866e3294aa04d0246784c38ccb5d4
parentb7dc2daf2af667f1816ecdb8561c5a21beca85a8 (diff)
downloadgvfs-sam/fuse-shutdown-on-error.tar.gz
fuse: Shutdown cleanly if an error occurs in vfs_init()sam/fuse-shutdown-on-error
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
-rw-r--r--client/gvfsfusedaemon.c54
1 files 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;