Skip to content

Commit 906d690

Browse files
committed
Merge branch 'ls/git-open-cloexec'
Git generally does not explicitly close file descriptors that were open in the parent process when spawning a child process, but most of the time the child does not want to access them. As Windows does not allow removing or renaming a file that has a file descriptor open, a slow-to-exit child can even break the parent process by holding onto them. Use O_CLOEXEC flag to open files in various codepaths. * ls/git-open-cloexec: read-cache: make sure file handles are not inherited by child processes sha1_file: open window into packfiles with O_CLOEXEC sha1_file: rename git_open_noatime() to git_open()
2 parents 7805bda + a0a6cb9 commit 906d690

File tree

5 files changed

+26
-14
lines changed

5 files changed

+26
-14
lines changed

builtin/pack-objects.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ static off_t write_reused_pack(struct sha1file *f)
720720
if (!is_pack_valid(reuse_packfile))
721721
die("packfile is invalid: %s", reuse_packfile->pack_name);
722722

723-
fd = git_open_noatime(reuse_packfile->pack_name);
723+
fd = git_open(reuse_packfile->pack_name);
724724
if (fd < 0)
725725
die_errno("unable to open packfile for reuse: %s",
726726
reuse_packfile->pack_name);

cache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,7 @@ extern int write_sha1_file(const void *buf, unsigned long len, const char *type,
11251125
extern int hash_sha1_file_literally(const void *buf, unsigned long len, const char *type, unsigned char *sha1, unsigned flags);
11261126
extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
11271127
extern int force_object_loose(const unsigned char *sha1, time_t mtime);
1128-
extern int git_open_noatime(const char *name);
1128+
extern int git_open(const char *name);
11291129
extern void *map_sha1_file(const unsigned char *sha1, unsigned long *size);
11301130
extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
11311131
extern int parse_sha1_header(const char *hdr, unsigned long *sizep);

pack-bitmap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ static int open_pack_bitmap_1(struct packed_git *packfile)
266266
return -1;
267267

268268
idx_name = pack_bitmap_filename(packfile);
269-
fd = git_open_noatime(idx_name);
269+
fd = git_open(idx_name);
270270
free(idx_name);
271271

272272
if (fd < 0)

read-cache.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,14 @@ void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
156156
static int ce_compare_data(const struct cache_entry *ce, struct stat *st)
157157
{
158158
int match = -1;
159-
int fd = open(ce->name, O_RDONLY);
159+
static int cloexec = O_CLOEXEC;
160+
int fd = open(ce->name, O_RDONLY | cloexec);
161+
162+
if ((cloexec & O_CLOEXEC) && fd < 0 && errno == EINVAL) {
163+
/* Try again w/o O_CLOEXEC: the kernel might not support it */
164+
cloexec &= ~O_CLOEXEC;
165+
fd = open(ce->name, O_RDONLY | cloexec);
166+
}
160167

161168
if (fd >= 0) {
162169
unsigned char sha1[20];

sha1_file.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ void read_info_alternates(const char * relative_base, int depth)
370370
int fd;
371371

372372
path = xstrfmt("%s/info/alternates", relative_base);
373-
fd = git_open_noatime(path);
373+
fd = git_open(path);
374374
free(path);
375375
if (fd < 0)
376376
return;
@@ -663,7 +663,7 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)
663663
struct pack_idx_header *hdr;
664664
size_t idx_size;
665665
uint32_t version, nr, i, *index;
666-
int fd = git_open_noatime(path);
666+
int fd = git_open(path);
667667
struct stat st;
668668

669669
if (fd < 0)
@@ -1069,7 +1069,7 @@ static int open_packed_git_1(struct packed_git *p)
10691069
while (pack_max_fds <= pack_open_fds && close_one_pack())
10701070
; /* nothing */
10711071

1072-
p->pack_fd = git_open_noatime(p->pack_name);
1072+
p->pack_fd = git_open(p->pack_name);
10731073
if (p->pack_fd < 0 || fstat(p->pack_fd, &st))
10741074
return -1;
10751075
pack_open_fds++;
@@ -1586,9 +1586,9 @@ int check_sha1_signature(const unsigned char *sha1, void *map,
15861586
return hashcmp(sha1, real_sha1) ? -1 : 0;
15871587
}
15881588

1589-
int git_open_noatime(const char *name)
1589+
int git_open(const char *name)
15901590
{
1591-
static int sha1_file_open_flag = O_NOATIME;
1591+
static int sha1_file_open_flag = O_NOATIME | O_CLOEXEC;
15921592

15931593
for (;;) {
15941594
int fd;
@@ -1598,12 +1598,17 @@ int git_open_noatime(const char *name)
15981598
if (fd >= 0)
15991599
return fd;
16001600

1601-
/* Might the failure be due to O_NOATIME? */
1602-
if (errno != ENOENT && sha1_file_open_flag) {
1603-
sha1_file_open_flag = 0;
1601+
/* Try again w/o O_CLOEXEC: the kernel might not support it */
1602+
if ((sha1_file_open_flag & O_CLOEXEC) && errno == EINVAL) {
1603+
sha1_file_open_flag &= ~O_CLOEXEC;
16041604
continue;
16051605
}
16061606

1607+
/* Might the failure be due to O_NOATIME? */
1608+
if (errno != ENOENT && (sha1_file_open_flag & O_NOATIME)) {
1609+
sha1_file_open_flag &= ~O_NOATIME;
1610+
continue;
1611+
}
16071612
return -1;
16081613
}
16091614
}
@@ -1632,15 +1637,15 @@ static int open_sha1_file(const unsigned char *sha1)
16321637
struct alternate_object_database *alt;
16331638
int most_interesting_errno;
16341639

1635-
fd = git_open_noatime(sha1_file_name(sha1));
1640+
fd = git_open(sha1_file_name(sha1));
16361641
if (fd >= 0)
16371642
return fd;
16381643
most_interesting_errno = errno;
16391644

16401645
prepare_alt_odb();
16411646
for (alt = alt_odb_list; alt; alt = alt->next) {
16421647
const char *path = alt_sha1_path(alt, sha1);
1643-
fd = git_open_noatime(path);
1648+
fd = git_open(path);
16441649
if (fd >= 0)
16451650
return fd;
16461651
if (most_interesting_errno == ENOENT)

0 commit comments

Comments
 (0)