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()
This commit is contained in:
commit
906d6906fb
@ -720,7 +720,7 @@ static off_t write_reused_pack(struct sha1file *f)
|
|||||||
if (!is_pack_valid(reuse_packfile))
|
if (!is_pack_valid(reuse_packfile))
|
||||||
die("packfile is invalid: %s", reuse_packfile->pack_name);
|
die("packfile is invalid: %s", reuse_packfile->pack_name);
|
||||||
|
|
||||||
fd = git_open_noatime(reuse_packfile->pack_name);
|
fd = git_open(reuse_packfile->pack_name);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
die_errno("unable to open packfile for reuse: %s",
|
die_errno("unable to open packfile for reuse: %s",
|
||||||
reuse_packfile->pack_name);
|
reuse_packfile->pack_name);
|
||||||
|
2
cache.h
2
cache.h
@ -1125,7 +1125,7 @@ extern int write_sha1_file(const void *buf, unsigned long len, const char *type,
|
|||||||
extern int hash_sha1_file_literally(const void *buf, unsigned long len, const char *type, unsigned char *sha1, unsigned flags);
|
extern int hash_sha1_file_literally(const void *buf, unsigned long len, const char *type, unsigned char *sha1, unsigned flags);
|
||||||
extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
|
extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
|
||||||
extern int force_object_loose(const unsigned char *sha1, time_t mtime);
|
extern int force_object_loose(const unsigned char *sha1, time_t mtime);
|
||||||
extern int git_open_noatime(const char *name);
|
extern int git_open(const char *name);
|
||||||
extern void *map_sha1_file(const unsigned char *sha1, unsigned long *size);
|
extern void *map_sha1_file(const unsigned char *sha1, unsigned long *size);
|
||||||
extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
|
extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
|
||||||
extern int parse_sha1_header(const char *hdr, unsigned long *sizep);
|
extern int parse_sha1_header(const char *hdr, unsigned long *sizep);
|
||||||
|
@ -266,7 +266,7 @@ static int open_pack_bitmap_1(struct packed_git *packfile)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
idx_name = pack_bitmap_filename(packfile);
|
idx_name = pack_bitmap_filename(packfile);
|
||||||
fd = git_open_noatime(idx_name);
|
fd = git_open(idx_name);
|
||||||
free(idx_name);
|
free(idx_name);
|
||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
|
@ -156,7 +156,14 @@ void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
|
|||||||
static int ce_compare_data(const struct cache_entry *ce, struct stat *st)
|
static int ce_compare_data(const struct cache_entry *ce, struct stat *st)
|
||||||
{
|
{
|
||||||
int match = -1;
|
int match = -1;
|
||||||
int fd = open(ce->name, O_RDONLY);
|
static int cloexec = O_CLOEXEC;
|
||||||
|
int fd = open(ce->name, O_RDONLY | cloexec);
|
||||||
|
|
||||||
|
if ((cloexec & O_CLOEXEC) && fd < 0 && errno == EINVAL) {
|
||||||
|
/* Try again w/o O_CLOEXEC: the kernel might not support it */
|
||||||
|
cloexec &= ~O_CLOEXEC;
|
||||||
|
fd = open(ce->name, O_RDONLY | cloexec);
|
||||||
|
}
|
||||||
|
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
|
25
sha1_file.c
25
sha1_file.c
@ -370,7 +370,7 @@ void read_info_alternates(const char * relative_base, int depth)
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
path = xstrfmt("%s/info/alternates", relative_base);
|
path = xstrfmt("%s/info/alternates", relative_base);
|
||||||
fd = git_open_noatime(path);
|
fd = git_open(path);
|
||||||
free(path);
|
free(path);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return;
|
return;
|
||||||
@ -663,7 +663,7 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)
|
|||||||
struct pack_idx_header *hdr;
|
struct pack_idx_header *hdr;
|
||||||
size_t idx_size;
|
size_t idx_size;
|
||||||
uint32_t version, nr, i, *index;
|
uint32_t version, nr, i, *index;
|
||||||
int fd = git_open_noatime(path);
|
int fd = git_open(path);
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
@ -1069,7 +1069,7 @@ static int open_packed_git_1(struct packed_git *p)
|
|||||||
while (pack_max_fds <= pack_open_fds && close_one_pack())
|
while (pack_max_fds <= pack_open_fds && close_one_pack())
|
||||||
; /* nothing */
|
; /* nothing */
|
||||||
|
|
||||||
p->pack_fd = git_open_noatime(p->pack_name);
|
p->pack_fd = git_open(p->pack_name);
|
||||||
if (p->pack_fd < 0 || fstat(p->pack_fd, &st))
|
if (p->pack_fd < 0 || fstat(p->pack_fd, &st))
|
||||||
return -1;
|
return -1;
|
||||||
pack_open_fds++;
|
pack_open_fds++;
|
||||||
@ -1586,9 +1586,9 @@ int check_sha1_signature(const unsigned char *sha1, void *map,
|
|||||||
return hashcmp(sha1, real_sha1) ? -1 : 0;
|
return hashcmp(sha1, real_sha1) ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_open_noatime(const char *name)
|
int git_open(const char *name)
|
||||||
{
|
{
|
||||||
static int sha1_file_open_flag = O_NOATIME;
|
static int sha1_file_open_flag = O_NOATIME | O_CLOEXEC;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int fd;
|
int fd;
|
||||||
@ -1598,12 +1598,17 @@ int git_open_noatime(const char *name)
|
|||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
/* Might the failure be due to O_NOATIME? */
|
/* Try again w/o O_CLOEXEC: the kernel might not support it */
|
||||||
if (errno != ENOENT && sha1_file_open_flag) {
|
if ((sha1_file_open_flag & O_CLOEXEC) && errno == EINVAL) {
|
||||||
sha1_file_open_flag = 0;
|
sha1_file_open_flag &= ~O_CLOEXEC;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Might the failure be due to O_NOATIME? */
|
||||||
|
if (errno != ENOENT && (sha1_file_open_flag & O_NOATIME)) {
|
||||||
|
sha1_file_open_flag &= ~O_NOATIME;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1632,7 +1637,7 @@ static int open_sha1_file(const unsigned char *sha1)
|
|||||||
struct alternate_object_database *alt;
|
struct alternate_object_database *alt;
|
||||||
int most_interesting_errno;
|
int most_interesting_errno;
|
||||||
|
|
||||||
fd = git_open_noatime(sha1_file_name(sha1));
|
fd = git_open(sha1_file_name(sha1));
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
return fd;
|
return fd;
|
||||||
most_interesting_errno = errno;
|
most_interesting_errno = errno;
|
||||||
@ -1640,7 +1645,7 @@ static int open_sha1_file(const unsigned char *sha1)
|
|||||||
prepare_alt_odb();
|
prepare_alt_odb();
|
||||||
for (alt = alt_odb_list; alt; alt = alt->next) {
|
for (alt = alt_odb_list; alt; alt = alt->next) {
|
||||||
const char *path = alt_sha1_path(alt, sha1);
|
const char *path = alt_sha1_path(alt, sha1);
|
||||||
fd = git_open_noatime(path);
|
fd = git_open(path);
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
return fd;
|
return fd;
|
||||||
if (most_interesting_errno == ENOENT)
|
if (most_interesting_errno == ENOENT)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user