PR 67585 Handle EINTR
Many POSIX systems have the bad habit of not restarting interrupted syscalls. On these systems it's up to the user to check for an error with errno == EINTR and restart manually. This patch does this for libgfortran, so that GFortran users don't have to do it. 2016-10-09 Janne Blomqvist <jb@gcc.gnu.org> PR libfortran/67585 * io/io.h: TEMP_FAILURE_RETRY: Define macro if not found. * io/unix.c (raw_read): Handle EINTR. (raw_write): Check for return value -1. (raw_seek): Handle EINTR. (raw_tell): Likewise. (raw_size): Likewise. (raw_truncate): Likewise. (raw_close): Likewise. (buf_flush): Call raw_seek instead of lseek. (buf_read): Likewise. (buf_write): Likewise. (fd_to_stream): Handle EINTR. (tempfile_open): Likewise. (regular_file2): Likewise. (compare_file_filename): Likewise. (find_file): Likewise. (inquire_sequential): Likewise. (inquire_direct): Likewise. (inquire_formatted): Likewise. From-SVN: r240902
This commit is contained in:
parent
df74f099d3
commit
b923394429
3 changed files with 98 additions and 26 deletions
|
@ -1,3 +1,26 @@
|
|||
2016-10-09 Janne Blomqvist <jb@gcc.gnu.org>
|
||||
|
||||
PR libfortran/67585
|
||||
* io/io.h: TEMP_FAILURE_RETRY: Define macro if not found.
|
||||
* io/unix.c (raw_read): Handle EINTR.
|
||||
(raw_write): Check for return value -1.
|
||||
(raw_seek): Handle EINTR.
|
||||
(raw_tell): Likewise.
|
||||
(raw_size): Likewise.
|
||||
(raw_truncate): Likewise.
|
||||
(raw_close): Likewise.
|
||||
(buf_flush): Call raw_seek instead of lseek.
|
||||
(buf_read): Likewise.
|
||||
(buf_write): Likewise.
|
||||
(fd_to_stream): Handle EINTR.
|
||||
(tempfile_open): Likewise.
|
||||
(regular_file2): Likewise.
|
||||
(compare_file_filename): Likewise.
|
||||
(find_file): Likewise.
|
||||
(inquire_sequential): Likewise.
|
||||
(inquire_direct): Likewise.
|
||||
(inquire_formatted): Likewise.
|
||||
|
||||
2016-10-05 Jerry DeLisle <jvdelisle@gcc.gnu.org>
|
||||
|
||||
PR fortran/77868
|
||||
|
|
|
@ -660,6 +660,21 @@ typedef struct gfc_saved_unit
|
|||
}
|
||||
gfc_saved_unit;
|
||||
|
||||
/* TEMP_FAILURE_RETRY macro from glibc. */
|
||||
|
||||
#ifndef TEMP_FAILURE_RETRY
|
||||
/* Evaluate EXPRESSION, and repeat as long as it returns -1 with `errno'
|
||||
set to EINTR. */
|
||||
|
||||
# define TEMP_FAILURE_RETRY(expression) \
|
||||
(__extension__ \
|
||||
({ long int __result; \
|
||||
do __result = (long int) (expression); \
|
||||
while (__result == -1L && errno == EINTR); \
|
||||
__result; }))
|
||||
#endif
|
||||
|
||||
|
||||
/* unit.c */
|
||||
|
||||
/* Maximum file offset, computed at library initialization time. */
|
||||
|
|
|
@ -298,8 +298,15 @@ static ssize_t
|
|||
raw_read (unix_stream * s, void * buf, ssize_t nbyte)
|
||||
{
|
||||
/* For read we can't do I/O in a loop like raw_write does, because
|
||||
that will break applications that wait for interactive I/O. */
|
||||
return read (s->fd, buf, nbyte);
|
||||
that will break applications that wait for interactive I/O. We
|
||||
still can loop around EINTR, though. */
|
||||
while (true)
|
||||
{
|
||||
ssize_t trans = read (s->fd, buf, nbyte);
|
||||
if (trans == -1 && errno == EINTR)
|
||||
continue;
|
||||
return trans;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
|
@ -316,7 +323,7 @@ raw_write (unix_stream * s, const void * buf, ssize_t nbyte)
|
|||
while (bytes_left > 0)
|
||||
{
|
||||
trans = write (s->fd, buf_st, bytes_left);
|
||||
if (trans < 0)
|
||||
if (trans == -1)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
@ -333,22 +340,33 @@ raw_write (unix_stream * s, const void * buf, ssize_t nbyte)
|
|||
static gfc_offset
|
||||
raw_seek (unix_stream * s, gfc_offset offset, int whence)
|
||||
{
|
||||
return lseek (s->fd, offset, whence);
|
||||
while (true)
|
||||
{
|
||||
gfc_offset off = lseek (s->fd, offset, whence);
|
||||
if (off == (gfc_offset) -1 && errno == EINTR)
|
||||
continue;
|
||||
return off;
|
||||
}
|
||||
}
|
||||
|
||||
static gfc_offset
|
||||
raw_tell (unix_stream * s)
|
||||
{
|
||||
return lseek (s->fd, 0, SEEK_CUR);
|
||||
while (true)
|
||||
{
|
||||
gfc_offset off = lseek (s->fd, 0, SEEK_CUR);
|
||||
if (off == (gfc_offset) -1 && errno == EINTR)
|
||||
continue;
|
||||
return off;
|
||||
}
|
||||
}
|
||||
|
||||
static gfc_offset
|
||||
raw_size (unix_stream * s)
|
||||
{
|
||||
struct stat statbuf;
|
||||
int ret = fstat (s->fd, &statbuf);
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
if (TEMP_FAILURE_RETRY (fstat (s->fd, &statbuf)) == -1)
|
||||
return -1;
|
||||
if (S_ISREG (statbuf.st_mode))
|
||||
return statbuf.st_size;
|
||||
else
|
||||
|
@ -390,7 +408,9 @@ raw_truncate (unix_stream * s, gfc_offset length)
|
|||
lseek (s->fd, cur, SEEK_SET);
|
||||
return -1;
|
||||
#elif defined HAVE_FTRUNCATE
|
||||
return ftruncate (s->fd, length);
|
||||
if (TEMP_FAILURE_RETRY (ftruncate (s->fd, length)) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
#elif defined HAVE_CHSIZE
|
||||
return chsize (s->fd, length);
|
||||
#else
|
||||
|
@ -409,7 +429,17 @@ raw_close (unix_stream * s)
|
|||
else if (s->fd != STDOUT_FILENO
|
||||
&& s->fd != STDERR_FILENO
|
||||
&& s->fd != STDIN_FILENO)
|
||||
retval = close (s->fd);
|
||||
{
|
||||
retval = close (s->fd);
|
||||
/* close() and EINTR is special, as the file descriptor is
|
||||
deallocated before doing anything that might cause the
|
||||
operation to be interrupted. Thus if we get EINTR the best we
|
||||
can do is ignore it and continue (otherwise if we try again
|
||||
the file descriptor may have been allocated again to some
|
||||
other file). */
|
||||
if (retval == -1 && errno == EINTR)
|
||||
retval = errno = 0;
|
||||
}
|
||||
else
|
||||
retval = 0;
|
||||
free (s);
|
||||
|
@ -463,7 +493,7 @@ buf_flush (unix_stream * s)
|
|||
return 0;
|
||||
|
||||
if (s->physical_offset != s->buffer_offset
|
||||
&& lseek (s->fd, s->buffer_offset, SEEK_SET) < 0)
|
||||
&& raw_seek (s, s->buffer_offset, SEEK_SET) < 0)
|
||||
return -1;
|
||||
|
||||
writelen = raw_write (s, s->buffer, s->ndirty);
|
||||
|
@ -518,7 +548,7 @@ buf_read (unix_stream * s, void * buf, ssize_t nbyte)
|
|||
to_read = nbyte - nread;
|
||||
new_logical = s->logical_offset + nread;
|
||||
if (s->physical_offset != new_logical
|
||||
&& lseek (s->fd, new_logical, SEEK_SET) < 0)
|
||||
&& raw_seek (s, new_logical, SEEK_SET) < 0)
|
||||
return -1;
|
||||
s->buffer_offset = s->physical_offset = new_logical;
|
||||
if (to_read <= BUFFER_SIZE/2)
|
||||
|
@ -587,7 +617,7 @@ buf_write (unix_stream * s, const void * buf, ssize_t nbyte)
|
|||
{
|
||||
if (s->physical_offset != s->logical_offset)
|
||||
{
|
||||
if (lseek (s->fd, s->logical_offset, SEEK_SET) < 0)
|
||||
if (raw_seek (s, s->logical_offset, SEEK_SET) < 0)
|
||||
return -1;
|
||||
s->physical_offset = s->logical_offset;
|
||||
}
|
||||
|
@ -1025,7 +1055,7 @@ fd_to_stream (int fd, bool unformatted)
|
|||
|
||||
/* Get the current length of the file. */
|
||||
|
||||
if (fstat (fd, &statbuf) == -1)
|
||||
if (TEMP_FAILURE_RETRY (fstat (fd, &statbuf)) == -1)
|
||||
{
|
||||
s->st_dev = s->st_ino = -1;
|
||||
s->file_length = 0;
|
||||
|
@ -1134,9 +1164,9 @@ tempfile_open (const char *tempdir, char **fname)
|
|||
#endif
|
||||
|
||||
#if defined(HAVE_MKOSTEMP) && defined(O_CLOEXEC)
|
||||
fd = mkostemp (template, O_CLOEXEC);
|
||||
TEMP_FAILURE_RETRY (fd = mkostemp (template, O_CLOEXEC));
|
||||
#else
|
||||
fd = mkstemp (template);
|
||||
TEMP_FAILURE_RETRY (fd = mkstemp (template));
|
||||
set_close_on_exec (fd);
|
||||
#endif
|
||||
|
||||
|
@ -1178,7 +1208,7 @@ tempfile_open (const char *tempdir, char **fname)
|
|||
continue;
|
||||
}
|
||||
|
||||
fd = open (template, flags, S_IRUSR | S_IWUSR);
|
||||
TEMP_FAILURE_RETRY (fd = open (template, flags, S_IRUSR | S_IWUSR));
|
||||
}
|
||||
while (fd == -1 && errno == EEXIST);
|
||||
#ifndef O_CLOEXEC
|
||||
|
@ -1355,7 +1385,7 @@ regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags)
|
|||
#endif
|
||||
|
||||
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
||||
fd = open (path, rwflag | crflag, mode);
|
||||
TEMP_FAILURE_RETRY (fd = open (path, rwflag | crflag, mode));
|
||||
if (flags->action != ACTION_UNSPECIFIED)
|
||||
return fd;
|
||||
|
||||
|
@ -1373,7 +1403,7 @@ regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags)
|
|||
crflag2 = crflag & ~(O_CREAT);
|
||||
else
|
||||
crflag2 = crflag;
|
||||
fd = open (path, rwflag | crflag2, mode);
|
||||
TEMP_FAILURE_RETRY (fd = open (path, rwflag | crflag2, mode));
|
||||
if (fd >=0)
|
||||
{
|
||||
flags->action = ACTION_READ;
|
||||
|
@ -1385,7 +1415,7 @@ regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags)
|
|||
|
||||
/* retry for write-only access */
|
||||
rwflag = O_WRONLY;
|
||||
fd = open (path, rwflag | crflag, mode);
|
||||
TEMP_FAILURE_RETRY (fd = open (path, rwflag | crflag, mode));
|
||||
if (fd >=0)
|
||||
{
|
||||
flags->action = ACTION_WRITE;
|
||||
|
@ -1512,7 +1542,7 @@ compare_file_filename (gfc_unit *u, const char *name, int len)
|
|||
/* If the filename doesn't exist, then there is no match with the
|
||||
* existing file. */
|
||||
|
||||
if (stat (path, &st) < 0)
|
||||
if (TEMP_FAILURE_RETRY (stat (path, &st)) < 0)
|
||||
{
|
||||
ret = 0;
|
||||
goto done;
|
||||
|
@ -1614,7 +1644,7 @@ find_file (const char *file, gfc_charlen_type file_len)
|
|||
|
||||
char *path = fc_strdup (file, file_len);
|
||||
|
||||
if (stat (path, &st[0]) < 0)
|
||||
if (TEMP_FAILURE_RETRY (stat (path, &st[0])) < 0)
|
||||
{
|
||||
u = NULL;
|
||||
goto done;
|
||||
|
@ -1742,7 +1772,8 @@ file_size (const char *file, gfc_charlen_type file_len)
|
|||
{
|
||||
char *path = fc_strdup (file, file_len);
|
||||
struct stat statbuf;
|
||||
int err = stat (path, &statbuf);
|
||||
int err;
|
||||
TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
|
||||
free (path);
|
||||
if (err == -1)
|
||||
return -1;
|
||||
|
@ -1764,7 +1795,8 @@ inquire_sequential (const char *string, int len)
|
|||
return unknown;
|
||||
|
||||
char *path = fc_strdup (string, len);
|
||||
int err = stat (path, &statbuf);
|
||||
int err;
|
||||
TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
|
||||
free (path);
|
||||
if (err == -1)
|
||||
return unknown;
|
||||
|
@ -1792,7 +1824,8 @@ inquire_direct (const char *string, int len)
|
|||
return unknown;
|
||||
|
||||
char *path = fc_strdup (string, len);
|
||||
int err = stat (path, &statbuf);
|
||||
int err;
|
||||
TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
|
||||
free (path);
|
||||
if (err == -1)
|
||||
return unknown;
|
||||
|
@ -1820,7 +1853,8 @@ inquire_formatted (const char *string, int len)
|
|||
return unknown;
|
||||
|
||||
char *path = fc_strdup (string, len);
|
||||
int err = stat (path, &statbuf);
|
||||
int err;
|
||||
TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
|
||||
free (path);
|
||||
if (err == -1)
|
||||
return unknown;
|
||||
|
|
Loading…
Add table
Reference in a new issue