threads / patch / 43780

patchsyncing disk in a subprocess with a 60 seconds timeout.

Subject: [PATCH] syncing disk in a subprocess with a 60 seconds timeout.

## tl;dr

One message between Nov 7, 2006 and Nov 7, 2006. Diffs are folded; open one to read it.

replies: 0people: 1as markdown or json

Christian Thaeter· Nov 7, 2006, 09:07 UTC · lore

sync() can take excessive long time, up to hours in some circumstances. (eg. running badblocks on slow disk, dd'ing disk images, packet-writing on optical media) Running a prune is usually expected to start (and complete) soon, especially if it is initiated from a cron-script.

This patch forks the sync() in a background process and waits at most 60 seconds for
it's completion. If the sync doesnt complete in time or any other error occurs, prunning
is aborted and can be tried again a later time. Note that the sync() process will get
orphaned and sit around until syncing eventually completes.
---
 builtin-prune-packed.c |   35 +++++++++++++++++++++++++++++++++--
 1 files changed, 33 insertions(+), 2 deletions(-)
Show changes to builtin-prune-packed.c +33 −2
diff --git a/builtin-prune-packed.c b/builtin-prune-packed.c
index 24e3b0a..05ac696 100644
--- a/builtin-prune-packed.c
+++ b/builtin-prune-packed.c
@@ -1,5 +1,7 @@
 #include "builtin.h"
 #include "cache.h"
+#include <time.h>
+#include <sys/wait.h>
 
 static const char prune_packed_usage[] =
 "git-prune-packed [-n]";
@@ -53,11 +55,16 @@ void prune_packed_objects(int dryrun)
 	}
 }
 
+void sig_nop(int unused){(void)unused;};
+
 int cmd_prune_packed(int argc, const char **argv, const char *prefix)
 {
 	int i;
 	int dryrun = 0;
-
+	pid_t syncpid;
+	struct timespec synctimeout;
+	int sleeping;
+		
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
 
@@ -71,7 +78,31 @@ int cmd_prune_packed(int argc, const cha
 		/* Handle arguments here .. */
 		usage(prune_packed_usage);
 	}
-	sync();
+	
+	synctimeout.tv_sec = 60;
+	synctimeout.tv_nsec = 0;
+		
+	signal(SIGCLD, sig_nop);
+	syncpid = fork();
+	if (syncpid == 0) {
+		sync();
+		return 0;
+	}
+	else if (syncpid > 0) {
+		do {
+			if (waitpid(syncpid, NULL, WNOHANG) > 0)
+				break;
+			sleeping = nanosleep(&synctimeout, &synctimeout);
+			if (sleeping == -1) {
+				if (errno != EINTR)
+					die ("nanosleep error");
+			}
+			else
+				die ("coudn't sync within 60 seconds, nothing pruned");
+		} while (1);
+	}
+	else die("failed to fork sync process");
+	signal(SIGCLD, SIG_DFL);
 	prune_packed_objects(dryrun);
 	return 0;
 }
-- 
1.4.3.2

← back to recent threads