{"thread":{"id":"369","subject":"[PATCH] diff.c: clean temporary files","startedAt":"2005-04-28T04:51:20Z","lastAt":"2005-04-28T04:51:20Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"1991","messageId":"7v7jinbj1z.fsf@assigned-by-dhcp.cox.net","threadId":"369","inReplyTo":null,"subject":"[PATCH] diff.c: clean temporary files","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-04-28T04:51:20Z","receivedAt":"2005-04-28T04:51:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When diff-cache -p and friends are interrupted, they can leave\ntheir temporary files behind.  Also when the external diff\nprogram is killed instead of exiting (this usually happens when\npiping the output to a pager, which can cause SIGPIPE when the\nuser quits viewing the diff early), they incorrectly died\nwithout cleaning their temporary file.  This patch fixes these\nproblems.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\ndiff.c |   29 ++++++++++++++++++++++++-----\n1 files changed, 24 insertions(+), 5 deletions(-)\n\n# - [PATCH] diff-tree -p implies diff-tree -p -r\n# + 04/27 21:50 diff.c clean up temporary file.\n--- k/diff.c\n+++ l/diff.c\n@@ -3,6 +3,7 @@\n  */\n #include <sys/types.h>\n #include <sys/wait.h>\n+#include <signal.h>\n #include \"cache.h\"\n #include \"diff.h\"\n \n@@ -119,6 +120,9 @@ static void prepare_temp_file(const char\n \n \tif (!one->file_valid) {\n \tnot_a_valid_file:\n+\t\t/* A '-' entry produces this for file-2, and\n+\t\t * a '+' entry produces this for file-1.\n+\t\t */\n \t\ttemp->name = \"/dev/null\";\n \t\tstrcpy(temp->hex, \".\");\n \t\tstrcpy(temp->mode, \".\");\n@@ -139,7 +143,7 @@ static void prepare_temp_file(const char\n \t\t\t\tgoto not_a_valid_file;\n \t\t\tdie(\"stat(%s): %s\", temp->name, strerror(errno));\n \t\t}\n-\t\tstrcpy(temp->hex, \".\");\n+\t\tstrcpy(temp->hex, sha1_to_hex(null_sha1));\n \t\tsprintf(temp->mode, \"%06o\",\n \t\t\tS_IFREG |ce_permissions(st.st_mode));\n \t}\n@@ -180,6 +184,11 @@ static void remove_tempfile(void)\n \t\t}\n }\n \n+static void remove_tempfile_on_signal(int signo)\n+{\n+\tremove_tempfile();\n+}\n+\n /* An external diff command takes:\n  *\n  * diff-cmd name infile1 infile1-sha1 infile1-mode \\\n@@ -191,7 +200,8 @@ void run_external_diff(const char *name,\n \t\t       struct diff_spec *two)\n {\n \tstruct diff_tempfile *temp = diff_temp;\n-\tint pid, status;\n+\tpid_t pid;\n+\tint status;\n \tstatic int atexit_asked = 0;\n \n \tif (one && two) {\n@@ -203,6 +213,7 @@ void run_external_diff(const char *name,\n \t\t\tatexit_asked = 1;\n \t\t\tatexit(remove_tempfile);\n \t\t}\n+\t\tsignal(SIGINT, remove_tempfile_on_signal);\n \t}\n \n \tfflush(NULL);\n@@ -230,9 +241,17 @@ void run_external_diff(const char *name,\n \t\t\tprintf(\"* Unmerged path %s\\n\", name);\n \t\texit(0);\n \t}\n-\tif (waitpid(pid, &status, 0) < 0 || !WIFEXITED(status))\n-\t\tdie(\"diff program failed\");\n-\n+\tif (waitpid(pid, &status, 0) < 0 || !WIFEXITED(status)) {\n+\t\t/* We do not check the exit status because typically\n+\t\t * diff exits non-zero if files are different, and\n+\t\t * we are not interested in knowing that.  We *knew*\n+\t\t * they are different and that's why we ran diff\n+\t\t * in the first place!  However if it dies by a signal,\n+\t\t * we stop processing immediately.\n+\t\t */\n+\t\tremove_tempfile();\n+\t\tdie(\"external diff died unexpectedly.\\n\");\n+\t}\n \tremove_tempfile();\n }\n \n\n"}]}