[PATCH v3 16/20] insert: trap SIGINT and clean up

Peter Wang novalazy at gmail.com
Sat Jan 19 16:50:00 PST 2013


The only potentially long-running part of the 'insert' command should be
copying stdin to the 'tmp' file.  If SIGINT is received during the
copying process, abort and clean up the file in 'tmp'.  At all other
points, just ignore the signal and continue.
---
 notmuch-insert.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index 8012eb4..494a7b0 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -25,6 +25,21 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 
+static volatile sig_atomic_t interrupted;
+
+static void
+handle_sigint (unused (int sig))
+{
+    static char msg[] = "Stopping...         \n";
+
+    /* This write is "opportunistic", so it's okay to ignore the
+     * result.  It is not required for correctness, and if it does
+     * fail or produce a short write, we want to get out of the signal
+     * handler as quickly as possible, not retry it. */
+    IGNORE_RESULT (write (2, msg, sizeof (msg) - 1));
+    interrupted = 1;
+}
+
 /* Like gethostname but guarantees that a null-terminated hostname is
  * returned, even if it has to make one up.
  * Returns true unless hostname contains a slash. */
@@ -258,7 +273,7 @@ copy_stdin (int fdin, int fdout)
     ssize_t remain;
     ssize_t written;
 
-    for (;;) {
+    while (! interrupted) {
 	remain = read (fdin, buf, sizeof (buf));
 	if (remain == 0)
 	    break;
@@ -287,7 +302,7 @@ copy_stdin (int fdin, int fdout)
 	} while (remain > 0);
     }
 
-    return TRUE;
+    return ! interrupted;
 }
 
 /* Add the specified message file to the notmuch database, applying tags.
@@ -372,6 +387,7 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
 {
     notmuch_config_t *config;
     notmuch_database_t *notmuch;
+    struct sigaction action;
     const char *db_path;
     const char **new_tags;
     size_t new_tags_length;
@@ -443,6 +459,14 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
 	return 1;
     }
 
+    /* Setup our handler for SIGINT. We do not set SA_RESTART so that copying
+     * from standard input may be interrupted. */
+    memset (&action, 0, sizeof (struct sigaction));
+    action.sa_handler = handle_sigint;
+    sigemptyset (&action.sa_mask);
+    action.sa_flags = 0;
+    sigaction (SIGINT, &action, NULL);
+
     if (notmuch_database_open (notmuch_config_get_database_path (config),
 			       NOTMUCH_DATABASE_MODE_READ_WRITE, &notmuch))
 	return 1;
-- 
1.7.12.1



More information about the notmuch mailing list