Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Commit 9aa91af

Browse files
obliquegitster
authored andcommitted
wrapper.c: add xpread() similar to xread()
It is a common mistake to call read(2)/pread(2) and forget to anticipate that they may return error with EAGAIN/EINTR when the system call is interrupted. We have xread() helper to relieve callers of read(2) from having to worry about it; add xpread() helper to do the same for pread(2). Update the caller in the builtin/index-pack.c and the mmap emulation in compat/. Signed-off-by: Yiannis Marangos <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7bbc4e8 commit 9aa91af

File tree

4 files changed

+21
-4
lines changed

4 files changed

+21
-4
lines changed

builtin/index-pack.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ static void *unpack_data(struct object_entry *obj,
542542

543543
do {
544544
ssize_t n = (len < 64*1024) ? len : 64*1024;
545-
n = pread(pack_fd, inbuf, n, from);
545+
n = xpread(pack_fd, inbuf, n, from);
546546
if (n < 0)
547547
die_errno(_("cannot pread pack file"));
548548
if (!n)

compat/mmap.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,14 @@ void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t of
1414
}
1515

1616
while (n < length) {
17-
ssize_t count = pread(fd, (char *)start + n, length - n, offset + n);
17+
ssize_t count = xpread(fd, (char *)start + n, length - n, offset + n);
1818

1919
if (count == 0) {
2020
memset((char *)start+n, 0, length-n);
2121
break;
2222
}
2323

2424
if (count < 0) {
25-
if (errno == EAGAIN || errno == EINTR)
26-
continue;
2725
free(start);
2826
errno = EACCES;
2927
return MAP_FAILED;

git-compat-util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ extern void *xcalloc(size_t nmemb, size_t size);
534534
extern void *xmmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
535535
extern ssize_t xread(int fd, void *buf, size_t len);
536536
extern ssize_t xwrite(int fd, const void *buf, size_t len);
537+
extern ssize_t xpread(int fd, void *buf, size_t len, off_t offset);
537538
extern int xdup(int fd);
538539
extern FILE *xfdopen(int fd, const char *mode);
539540
extern int xmkstemp(char *template);

wrapper.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,24 @@ ssize_t xwrite(int fd, const void *buf, size_t len)
174174
}
175175
}
176176

177+
/*
178+
* xpread() is the same as pread(), but it automatically restarts pread()
179+
* operations with a recoverable error (EAGAIN and EINTR). xpread() DOES
180+
* NOT GUARANTEE that "len" bytes is read even if the data is available.
181+
*/
182+
ssize_t xpread(int fd, void *buf, size_t len, off_t offset)
183+
{
184+
ssize_t nr;
185+
if (len > MAX_IO_SIZE)
186+
len = MAX_IO_SIZE;
187+
while (1) {
188+
nr = pread(fd, buf, len, offset);
189+
if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
190+
continue;
191+
return nr;
192+
}
193+
}
194+
177195
ssize_t read_in_full(int fd, void *buf, size_t count)
178196
{
179197
char *p = buf;

0 commit comments

Comments
 (0)