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()
maint
Junio C Hamano 2016-10-31 13:15:21 -07:00
commit 906d6906fb
5 changed files with 26 additions and 14 deletions

View File

@ -720,7 +720,7 @@ static off_t write_reused_pack(struct sha1file *f)
if (!is_pack_valid(reuse_packfile))
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)
die_errno("unable to open packfile for reuse: %s",
reuse_packfile->pack_name);

View File

@ -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 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 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 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);

View File

@ -266,7 +266,7 @@ static int open_pack_bitmap_1(struct packed_git *packfile)
return -1;

idx_name = pack_bitmap_filename(packfile);
fd = git_open_noatime(idx_name);
fd = git_open(idx_name);
free(idx_name);

if (fd < 0)

View File

@ -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)
{
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) {
unsigned char sha1[20];

View File

@ -370,7 +370,7 @@ void read_info_alternates(const char * relative_base, int depth)
int fd;

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

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())
; /* 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))
return -1;
pack_open_fds++;
@ -1586,9 +1586,9 @@ int check_sha1_signature(const unsigned char *sha1, void *map,
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 (;;) {
int fd;
@ -1598,12 +1598,17 @@ int git_open_noatime(const char *name)
if (fd >= 0)
return fd;

/* Might the failure be due to O_NOATIME? */
if (errno != ENOENT && sha1_file_open_flag) {
sha1_file_open_flag = 0;
/* Try again w/o O_CLOEXEC: the kernel might not support it */
if ((sha1_file_open_flag & O_CLOEXEC) && errno == EINVAL) {
sha1_file_open_flag &= ~O_CLOEXEC;
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;
}
}
@ -1632,7 +1637,7 @@ static int open_sha1_file(const unsigned char *sha1)
struct alternate_object_database *alt;
int most_interesting_errno;

fd = git_open_noatime(sha1_file_name(sha1));
fd = git_open(sha1_file_name(sha1));
if (fd >= 0)
return fd;
most_interesting_errno = errno;
@ -1640,7 +1645,7 @@ static int open_sha1_file(const unsigned char *sha1)
prepare_alt_odb();
for (alt = alt_odb_list; alt; alt = alt->next) {
const char *path = alt_sha1_path(alt, sha1);
fd = git_open_noatime(path);
fd = git_open(path);
if (fd >= 0)
return fd;
if (most_interesting_errno == ENOENT)