Skip to content

Commit c55c306

Browse files
pks-tgitster
authored andcommitted
receive-pack: fix stale packfile locks when dying
When accepting a packfile in git-receive-pack(1), we feed that packfile into git-index-pack(1) to generate the packfile index. As the packfile would often only contain unreachable objects until the references have been updated, concurrently running garbage collection might be tempted to delete the packfile right away and thus cause corruption. To fix this, we ask git-index-pack(1) to create a `.keep` file before moving the packfile into place, which is getting deleted again once all of the reference updates have been processed. Now in production systems we have observed that those `.keep` files are sometimes not getting deleted as expected, where the result is that repositories tend to grow packfiles that are never deleted over time. This seems to be caused by a race when git-receive-pack(1) is killed after we have migrated the kept packfile from the quarantine directory into the main object database. While this race window is typically small it can be extended for example by installing a `proc-receive` hook. Fix this race by registering the lockfile as a tempfile so that it will automatically be removed at exit or when receiving a signal. Helped-by: Jeff King <[email protected]> Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7556e5d commit c55c306

File tree

1 file changed

+10
-4
lines changed

1 file changed

+10
-4
lines changed

builtin/receive-pack.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2171,7 +2171,7 @@ static const char *parse_pack_header(struct pack_header *hdr)
21712171
}
21722172
}
21732173

2174-
static const char *pack_lockfile;
2174+
static struct tempfile *pack_lockfile;
21752175

21762176
static void push_header_arg(struct strvec *args, struct pack_header *hdr)
21772177
{
@@ -2238,6 +2238,7 @@ static const char *unpack(int err_fd, struct shallow_info *si)
22382238
return "unpack-objects abnormal exit";
22392239
} else {
22402240
char hostname[HOST_NAME_MAX + 1];
2241+
char *lockfile;
22412242

22422243
strvec_pushl(&child.args, "index-pack", "--stdin", NULL);
22432244
push_header_arg(&child.args, &hdr);
@@ -2267,8 +2268,14 @@ static const char *unpack(int err_fd, struct shallow_info *si)
22672268
status = start_command(&child);
22682269
if (status)
22692270
return "index-pack fork failed";
2270-
pack_lockfile = index_pack_lockfile(child.out, NULL);
2271+
2272+
lockfile = index_pack_lockfile(child.out, NULL);
2273+
if (lockfile) {
2274+
pack_lockfile = register_tempfile(lockfile);
2275+
free(lockfile);
2276+
}
22712277
close(child.out);
2278+
22722279
status = finish_command(&child);
22732280
if (status)
22742281
return "index-pack abnormal exit";
@@ -2555,8 +2562,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
25552562
use_keepalive = KEEPALIVE_ALWAYS;
25562563
execute_commands(commands, unpack_status, &si,
25572564
&push_options);
2558-
if (pack_lockfile)
2559-
unlink_or_warn(pack_lockfile);
2565+
delete_tempfile(&pack_lockfile);
25602566
sigchain_push(SIGPIPE, SIG_IGN);
25612567
if (report_status_v2)
25622568
report_v2(commands, unpack_status);

0 commit comments

Comments
 (0)