tempfile: robustify cleanup handler
[gitweb.git] / tempfile.c
index 0e6c6b9c18f1b43d273eba5c7b9d1e03c301477c..3348ad59dd3beb44e3057856edffaddea40a24c1 100644 (file)
 
 static struct tempfile *volatile tempfile_list;
 
-static void remove_tempfiles(int skip_fclose)
+static void remove_tempfiles(int in_signal_handler)
 {
        pid_t me = getpid();
+       struct tempfile *volatile p;
 
-       while (tempfile_list) {
-               if (tempfile_list->owner == me) {
-                       /* fclose() is not safe to call in a signal handler */
-                       if (skip_fclose)
-                               tempfile_list->fp = NULL;
-                       delete_tempfile(tempfile_list);
-               }
-               tempfile_list = tempfile_list->next;
+       for (p = tempfile_list; p; p = p->next) {
+               if (!is_tempfile_active(p) || p->owner != me)
+                       continue;
+
+               if (p->fd >= 0)
+                       close(p->fd);
+
+               if (in_signal_handler)
+                       unlink(p->filename.buf);
+               else
+                       unlink_or_warn(p->filename.buf);
+
+               p->active = 0;
        }
 }
 
@@ -119,6 +125,12 @@ static void activate_tempfile(struct tempfile *tempfile)
        tempfile->active = 1;
 }
 
+static void deactivate_tempfile(struct tempfile *tempfile)
+{
+       tempfile->active = 0;
+       strbuf_reset(&tempfile->filename);
+}
+
 /* Make sure errno contains a meaningful value on error */
 int create_tempfile(struct tempfile *tempfile, const char *path)
 {
@@ -132,7 +144,7 @@ int create_tempfile(struct tempfile *tempfile, const char *path)
                tempfile->fd = open(tempfile->filename.buf,
                                    O_RDWR | O_CREAT | O_EXCL, 0666);
        if (tempfile->fd < 0) {
-               strbuf_reset(&tempfile->filename);
+               deactivate_tempfile(tempfile);
                return -1;
        }
        activate_tempfile(tempfile);
@@ -161,7 +173,7 @@ int mks_tempfile_sm(struct tempfile *tempfile,
        strbuf_add_absolute_path(&tempfile->filename, template);
        tempfile->fd = git_mkstemps_mode(tempfile->filename.buf, suffixlen, mode);
        if (tempfile->fd < 0) {
-               strbuf_reset(&tempfile->filename);
+               deactivate_tempfile(tempfile);
                return -1;
        }
        activate_tempfile(tempfile);
@@ -182,7 +194,7 @@ int mks_tempfile_tsm(struct tempfile *tempfile,
        strbuf_addf(&tempfile->filename, "%s/%s", tmpdir, template);
        tempfile->fd = git_mkstemps_mode(tempfile->filename.buf, suffixlen, mode);
        if (tempfile->fd < 0) {
-               strbuf_reset(&tempfile->filename);
+               deactivate_tempfile(tempfile);
                return -1;
        }
        activate_tempfile(tempfile);
@@ -291,8 +303,7 @@ int rename_tempfile(struct tempfile *tempfile, const char *path)
                return -1;
        }
 
-       tempfile->active = 0;
-       strbuf_reset(&tempfile->filename);
+       deactivate_tempfile(tempfile);
        return 0;
 }
 
@@ -303,6 +314,5 @@ void delete_tempfile(struct tempfile *tempfile)
 
        close_tempfile_gently(tempfile);
        unlink_or_warn(tempfile->filename.buf);
-       tempfile->active = 0;
-       strbuf_reset(&tempfile->filename);
+       deactivate_tempfile(tempfile);
 }