adds SIGINT handler to dav-sync

Sun, 10 Sep 2017 10:23:25 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 10 Sep 2017 10:23:25 +0200
changeset 302
395763c0ee69
parent 300
4e3769d4e782
child 304
a4d3ff32d49c

adds SIGINT handler to dav-sync

bsd.mk file | annotate | diff | comparison | revisions
clang.mk file | annotate | diff | comparison | revisions
dav/sync.c file | annotate | diff | comparison | revisions
dav/sync.h file | annotate | diff | comparison | revisions
gcc.mk file | annotate | diff | comparison | revisions
osx.mk file | annotate | diff | comparison | revisions
suncc.mk file | annotate | diff | comparison | revisions
--- a/bsd.mk	Thu Sep 07 18:42:51 2017 +0200
+++ b/bsd.mk	Sun Sep 10 10:23:25 2017 +0200
@@ -43,5 +43,5 @@
 APP_EXT =
 
 DAV_CFLAGS = `curl-config --cflags` `pkg-config --cflags libxml-2.0`
-DAV_LDFLAGS = `curl-config --libs` `pkg-config --libs libxml-2.0` -lssl -lcrypto
+DAV_LDFLAGS = `curl-config --libs` `pkg-config --libs libxml-2.0` -lssl -lcrypto -lpthread
 
--- a/clang.mk	Thu Sep 07 18:42:51 2017 +0200
+++ b/clang.mk	Sun Sep 10 10:23:25 2017 +0200
@@ -43,5 +43,5 @@
 APP_EXT =
 
 DAV_CFLAGS = `curl-config --cflags` `pkg-config --cflags openssl libxml-2.0`
-DAV_LDFLAGS = `curl-config --libs` `pkg-config --libs openssl libxml-2.0`
+DAV_LDFLAGS = `curl-config --libs` `pkg-config --libs openssl libxml-2.0` -lpthread
 
--- a/dav/sync.c	Thu Sep 07 18:42:51 2017 +0200
+++ b/dav/sync.c	Sun Sep 10 10:23:25 2017 +0200
@@ -31,6 +31,7 @@
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
+#include <signal.h>
 #include <time.h>
 #include <libxml/xmlerror.h>
 #include <sys/types.h>
@@ -52,8 +53,12 @@
 #include "sync.h"
 #include "libidav/session.h"
 
+#include <pthread.h>
+
 static DavContext *ctx;
 
+static int sync_shutdown = 0;
+
 static void xmlerrorfnc(void * c, const char * msg, ... ) {
     va_list ap;
     va_start(ap, msg);
@@ -88,6 +93,10 @@
     ctx = dav_context_new();
     int cfgret = load_config(ctx) || load_sync_config();
     
+    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+    pthread_mutex_lock(&mutex);
+    pthread_t tid;
+    
     if(!strcmp(cmd, "check") || !strcmp(cmd, "check-config")) {
         if(!cfgret) {
             fprintf(stdout, "Configuration OK.\n");
@@ -98,11 +107,17 @@
         }
     } else if(!cfgret) {
         if(!strcmp(cmd, "pull")) {
+            tid = start_sighandler(&mutex);
             ret = cmd_pull(args);
+            stop_sighandler(&mutex, tid);
         } else if(!strcmp(cmd, "push")) {
+            tid = start_sighandler(&mutex);
             ret = cmd_push(args, FALSE);
+            stop_sighandler(&mutex, tid);
         } else if(!strcmp(cmd, "archive")) {
+            tid = start_sighandler(&mutex);
             ret = cmd_push(args, TRUE);
+            stop_sighandler(&mutex, tid);
         } else if(!strcmp(cmd, "resolve-conflicts")) {
             ret = cmd_resolve_conflicts(args);
         } else if(!strcmp(cmd, "delete-conflicts")) {
@@ -164,6 +179,38 @@
     fprintf(stderr, "        check-repositories\n\n");
 }
 
+static void handlesig(int sig) {
+    if(sync_shutdown) {
+        exit(-1);
+    }
+    fprintf(stderr, "abort\n");
+    sync_shutdown = 1;
+}
+
+static void* sighandler(void *data) {
+    signal(SIGTERM, handlesig);
+    signal(SIGINT, handlesig);
+    
+    pthread_mutex_t *mutex = data;
+    pthread_mutex_lock(mutex); // block thread
+    return NULL;
+}
+
+pthread_t start_sighandler(pthread_mutex_t *mutex) {
+    pthread_t tid;
+    if(pthread_create(&tid, NULL, sighandler, mutex)) {
+        perror("pthread_create");
+        exit(-1);
+    }
+    return tid;
+}
+
+void stop_sighandler(pthread_mutex_t *mutex, pthread_t tid) {
+    pthread_mutex_unlock(mutex);
+    void *data;
+    pthread_join(tid, &data);
+}
+
 static int res_matches_filter(SyncDirectory *dir, char *res_path) {
     // trash filter
     if (dir->trash) {
@@ -336,7 +383,7 @@
             }
             
             // download the resource
-            if(sync_get_resource(a, dir, res, db, &sync_success)) {
+            if(!sync_shutdown && sync_get_resource(a, dir, res, db, &sync_success)) {
                 fprintf(stderr, "sync_get_resource failed for resource: %s\n", res->path);
                 sync_error++;
             }
@@ -344,14 +391,15 @@
             // add every resource from the server to svrres
             // then db-resources contains only resources which are not on the
             // server
-            LocalResource *local = ucx_map_cstr_get(db->resources, res->path);
-            ucx_map_cstr_put(svrres, res->path, local);
-            ucx_map_cstr_remove(db->resources, res->path);
-            
-            if(local->last_modified == 0) {
-                // stat this file later (directory)
-                statls = ucx_list_prepend(statls, local);
-            }
+            LocalResource *local = ucx_map_cstr_remove(db->resources, res->path);
+            if(local) {
+                ucx_map_cstr_put(svrres, res->path, local);
+                
+                if(local->last_modified == 0) {
+                    // stat this file later (directory)
+                    statls = ucx_list_prepend(statls, local);
+                }
+            } // else: sync_shutdown is TRUE
             
             if(res->children) {
                 stack = ucx_list_prepend(stack, res->children);
@@ -380,12 +428,17 @@
         if (res_matches_filter(dir, local->path)) {
             continue;
         }
-        // sync_remove_resource does all necessary tests
-        int ret = sync_remove_local_resource(dir, local);
-        if(ret == -1) {
-            rmdirs = ucx_list_append(rmdirs, local);
-        } else if(ret == 0) {
-            sync_delete++;
+        
+        if(sync_shutdown) {
+            ucx_map_cstr_put(svrres, local->path, local_resource_copy(local));
+        } else {
+            // sync_remove_resource does all necessary tests
+            int ret = sync_remove_local_resource(dir, local);
+            if(ret == -1) {
+                rmdirs = ucx_list_append(rmdirs, local);
+            } else if(ret == 0) {
+                sync_delete++;
+            }
         }
     }
     UCX_FOREACH(elm, rmdirs) {
@@ -823,12 +876,26 @@
     UCX_FOREACH(elm, resources) {
         LocalResource *local_res = elm->data;
         if (!res_matches_filter(dir, local_res->path+1)) {
+            if(sync_shutdown) {
+                LocalResource *lr = ucx_map_cstr_remove(db->resources, local_res->path);
+                if(lr) {
+                    local_res->size = lr->size;
+                    local_res->last_modified = lr->last_modified;
+                    local_res->etag = lr->etag ? strdup(lr->etag) : NULL;
+                    local_resource_free(lr);
+                    ucx_map_cstr_put(lclres, local_res->path, local_res);
+                }
+                elm->data = NULL;
+                continue;
+            }
+            
+            
             if(res_isconflict(db, local_res)) {
                 printf("skip: %s\n", local_res->path);
                 sync_skipped++;
                 continue;
             }
-            
+                       
             // upload every changed file
             int error = 0;
             if (local_resource_is_changed(dir, db, local_res)) {
@@ -886,8 +953,10 @@
         LocalResource *local;
         UCX_MAP_FOREACH(key, local, i) {
             if (!res_matches_filter(dir, local->path+1)) {
-                if(sync_delete_remote_resource(sn, local, &sync_delete)) {
-                    ucx_map_cstr_put(lclres, local->path, local);
+                if(sync_shutdown) {
+                    ucx_map_cstr_put(lclres, local->path, local_resource_copy(local));
+                } else if(sync_delete_remote_resource(sn, local, &sync_delete)) {
+                    ucx_map_cstr_put(lclres, local->path, local_resource_copy(local));
                     if(sn->error != DAV_NOT_FOUND) {
                         print_resource_error(sn, local->path);
                         sync_error++;
@@ -1070,6 +1139,24 @@
     }
 }
 
+LocalResource* local_resource_copy(LocalResource *res) {
+    LocalResource *newres = calloc(1, sizeof(LocalResource));
+    if(res->name) {
+        newres->name = strdup(res->name);
+    }
+    if(res->path) {
+        newres->path = strdup(res->path);
+    }
+    if(res->etag) {
+        newres->etag = strdup(res->etag);
+    }
+    newres->skipped = res->skipped;
+    newres->size = res->size;
+    newres->last_modified = res->last_modified;
+    newres->isdirectory = res->isdirectory;
+    return newres;
+}
+
 int local_resource_is_changed(SyncDirectory *dir, SyncDatabase *db, LocalResource *res) {
     LocalResource *db_res = ucx_map_cstr_get(db->resources, res->path);
     if(db_res) {
--- a/dav/sync.h	Thu Sep 07 18:42:51 2017 +0200
+++ b/dav/sync.h	Sun Sep 10 10:23:25 2017 +0200
@@ -37,14 +37,23 @@
 
 #include "version.h"
 
+#ifdef _WIN32
+// TODO: thread includes
+#else
+#include <pthread.h>
+#endif /* _WIN32 */
+
 #ifdef	__cplusplus
 extern "C" {
 #endif
 
 #define STDIN_BUF_SIZE 2048
-    
+
 void print_usage(char *cmd);
 
+pthread_t start_sighandler(pthread_mutex_t *mutex) ;
+void stop_sighandler(pthread_mutex_t *mutex, pthread_t tid);
+
 int cmd_pull(CmdArgs *args);
 int cmd_push(CmdArgs *args, DavBool archive);
 
@@ -62,6 +71,7 @@
 UcxList* local_scan(SyncDirectory *dir, SyncDatabase *db);
 UcxList* read_changes(SyncDirectory *dir, SyncDatabase *db);
 LocalResource* local_resource_new(SyncDirectory *dir, SyncDatabase *db, char *path, int *isdir);
+LocalResource* local_resource_copy(LocalResource *res);
 int local_resource_is_changed(SyncDirectory *dir, SyncDatabase *db, LocalResource *res);
 int remote_resource_is_changed(
         DavSession *sn,
--- a/gcc.mk	Thu Sep 07 18:42:51 2017 +0200
+++ b/gcc.mk	Sun Sep 10 10:23:25 2017 +0200
@@ -43,5 +43,5 @@
 APP_EXT =
 
 DAV_CFLAGS = `curl-config --cflags` `pkg-config --cflags openssl libxml-2.0`
-DAV_LDFLAGS = `curl-config --libs` `pkg-config --libs openssl libxml-2.0`
+DAV_LDFLAGS = `curl-config --libs` `pkg-config --libs openssl libxml-2.0` -lpthread
 
--- a/osx.mk	Thu Sep 07 18:42:51 2017 +0200
+++ b/osx.mk	Sun Sep 10 10:23:25 2017 +0200
@@ -43,4 +43,4 @@
 APP_EXT =
 
 DAV_CFLAGS = `xml2-config --cflags`
-DAV_LDFLAGS = -lcurl -lxml2 -lssl -lcrypto
+DAV_LDFLAGS = -lcurl -lxml2 -lssl -lcrypto -lpthread
--- a/suncc.mk	Thu Sep 07 18:42:51 2017 +0200
+++ b/suncc.mk	Sun Sep 10 10:23:25 2017 +0200
@@ -43,5 +43,5 @@
 APP_EXT =
 
 DAV_CFLAGS = `curl-config --cflags` `pkg-config --cflags openssl libxml-2.0`
-DAV_LDFLAGS = `pkg-config --libs openssl libxml-2.0` `curl-config --libs` 
+DAV_LDFLAGS = `pkg-config --libs openssl libxml-2.0` `curl-config --libs` -lpthread
 

mercurial