{"thread":{"id":"43780","subject":"[PATCH] syncing disk in a subprocess with a 60 seconds timeout.","startedAt":"2006-11-07T09:07:56Z","lastAt":"2006-11-07T09:07:56Z","messageCount":1,"participants":["Christian Thaeter"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"298687","messageId":"20061107092208.798A3F7044@mail.pipapo.org","threadId":"43780","inReplyTo":null,"subject":"[PATCH] syncing disk in a subprocess with a 60 seconds timeout.","fromName":"Christian Thaeter","fromEmail":"ct@pipapo.org","sentAt":"2006-11-07T09:07:56Z","receivedAt":"2006-11-07T09:07:56Z","isPatch":true,"sender":{"key":"ct@pipapo.org","avatar":null},"body":"sync() can take excessive long time, up to hours in some circumstances.\n(eg. running badblocks on slow disk, dd'ing disk images, packet-writing on optical media)\nRunning a prune is usually expected to start (and complete) soon, especially\nif it is initiated from a cron-script.\n\nThis patch forks the sync() in a background process and waits at most 60 seconds for\nit's completion. If the sync doesnt complete in time or any other error occurs, prunning\nis aborted and can be tried again a later time. Note that the sync() process will get\norphaned and sit around until syncing eventually completes.\n---\n builtin-prune-packed.c |   35 +++++++++++++++++++++++++++++++++--\n 1 files changed, 33 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin-prune-packed.c b/builtin-prune-packed.c\nindex 24e3b0a..05ac696 100644\n--- a/builtin-prune-packed.c\n+++ b/builtin-prune-packed.c\n@@ -1,5 +1,7 @@\n #include \"builtin.h\"\n #include \"cache.h\"\n+#include <time.h>\n+#include <sys/wait.h>\n \n static const char prune_packed_usage[] =\n \"git-prune-packed [-n]\";\n@@ -53,11 +55,16 @@ void prune_packed_objects(int dryrun)\n \t}\n }\n \n+void sig_nop(int unused){(void)unused;};\n+\n int cmd_prune_packed(int argc, const char **argv, const char *prefix)\n {\n \tint i;\n \tint dryrun = 0;\n-\n+\tpid_t syncpid;\n+\tstruct timespec synctimeout;\n+\tint sleeping;\n+\t\t\n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n \n@@ -71,7 +78,31 @@ int cmd_prune_packed(int argc, const cha\n \t\t/* Handle arguments here .. */\n \t\tusage(prune_packed_usage);\n \t}\n-\tsync();\n+\t\n+\tsynctimeout.tv_sec = 60;\n+\tsynctimeout.tv_nsec = 0;\n+\t\t\n+\tsignal(SIGCLD, sig_nop);\n+\tsyncpid = fork();\n+\tif (syncpid == 0) {\n+\t\tsync();\n+\t\treturn 0;\n+\t}\n+\telse if (syncpid > 0) {\n+\t\tdo {\n+\t\t\tif (waitpid(syncpid, NULL, WNOHANG) > 0)\n+\t\t\t\tbreak;\n+\t\t\tsleeping = nanosleep(&synctimeout, &synctimeout);\n+\t\t\tif (sleeping == -1) {\n+\t\t\t\tif (errno != EINTR)\n+\t\t\t\t\tdie (\"nanosleep error\");\n+\t\t\t}\n+\t\t\telse\n+\t\t\t\tdie (\"coudn't sync within 60 seconds, nothing pruned\");\n+\t\t} while (1);\n+\t}\n+\telse die(\"failed to fork sync process\");\n+\tsignal(SIGCLD, SIG_DFL);\n \tprune_packed_objects(dryrun);\n \treturn 0;\n }\n-- \n1.4.3.2\n"}]}