Commit b9233944 by Janne Blomqvist

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
parent df74f099
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> 2016-10-05 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/77868 PR fortran/77868
......
...@@ -660,6 +660,21 @@ typedef struct gfc_saved_unit ...@@ -660,6 +660,21 @@ typedef struct gfc_saved_unit
} }
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 */ /* unit.c */
/* Maximum file offset, computed at library initialization time. */ /* Maximum file offset, computed at library initialization time. */
......
...@@ -298,8 +298,15 @@ static ssize_t ...@@ -298,8 +298,15 @@ static ssize_t
raw_read (unix_stream * s, void * buf, ssize_t nbyte) 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 /* 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. */ that will break applications that wait for interactive I/O. We
return read (s->fd, buf, nbyte); 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 static ssize_t
...@@ -316,7 +323,7 @@ raw_write (unix_stream * s, const void * buf, ssize_t nbyte) ...@@ -316,7 +323,7 @@ raw_write (unix_stream * s, const void * buf, ssize_t nbyte)
while (bytes_left > 0) while (bytes_left > 0)
{ {
trans = write (s->fd, buf_st, bytes_left); trans = write (s->fd, buf_st, bytes_left);
if (trans < 0) if (trans == -1)
{ {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
...@@ -333,22 +340,33 @@ raw_write (unix_stream * s, const void * buf, ssize_t nbyte) ...@@ -333,22 +340,33 @@ raw_write (unix_stream * s, const void * buf, ssize_t nbyte)
static gfc_offset static gfc_offset
raw_seek (unix_stream * s, gfc_offset offset, int whence) 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 static gfc_offset
raw_tell (unix_stream * s) 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 static gfc_offset
raw_size (unix_stream * s) raw_size (unix_stream * s)
{ {
struct stat statbuf; struct stat statbuf;
int ret = fstat (s->fd, &statbuf); if (TEMP_FAILURE_RETRY (fstat (s->fd, &statbuf)) == -1)
if (ret == -1) return -1;
return ret;
if (S_ISREG (statbuf.st_mode)) if (S_ISREG (statbuf.st_mode))
return statbuf.st_size; return statbuf.st_size;
else else
...@@ -390,7 +408,9 @@ raw_truncate (unix_stream * s, gfc_offset length) ...@@ -390,7 +408,9 @@ raw_truncate (unix_stream * s, gfc_offset length)
lseek (s->fd, cur, SEEK_SET); lseek (s->fd, cur, SEEK_SET);
return -1; return -1;
#elif defined HAVE_FTRUNCATE #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 #elif defined HAVE_CHSIZE
return chsize (s->fd, length); return chsize (s->fd, length);
#else #else
...@@ -409,7 +429,17 @@ raw_close (unix_stream * s) ...@@ -409,7 +429,17 @@ raw_close (unix_stream * s)
else if (s->fd != STDOUT_FILENO else if (s->fd != STDOUT_FILENO
&& s->fd != STDERR_FILENO && s->fd != STDERR_FILENO
&& s->fd != STDIN_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 else
retval = 0; retval = 0;
free (s); free (s);
...@@ -463,7 +493,7 @@ buf_flush (unix_stream * s) ...@@ -463,7 +493,7 @@ buf_flush (unix_stream * s)
return 0; return 0;
if (s->physical_offset != s->buffer_offset 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; return -1;
writelen = raw_write (s, s->buffer, s->ndirty); writelen = raw_write (s, s->buffer, s->ndirty);
...@@ -518,7 +548,7 @@ buf_read (unix_stream * s, void * buf, ssize_t nbyte) ...@@ -518,7 +548,7 @@ buf_read (unix_stream * s, void * buf, ssize_t nbyte)
to_read = nbyte - nread; to_read = nbyte - nread;
new_logical = s->logical_offset + nread; new_logical = s->logical_offset + nread;
if (s->physical_offset != new_logical if (s->physical_offset != new_logical
&& lseek (s->fd, new_logical, SEEK_SET) < 0) && raw_seek (s, new_logical, SEEK_SET) < 0)
return -1; return -1;
s->buffer_offset = s->physical_offset = new_logical; s->buffer_offset = s->physical_offset = new_logical;
if (to_read <= BUFFER_SIZE/2) if (to_read <= BUFFER_SIZE/2)
...@@ -587,7 +617,7 @@ buf_write (unix_stream * s, const void * buf, ssize_t nbyte) ...@@ -587,7 +617,7 @@ buf_write (unix_stream * s, const void * buf, ssize_t nbyte)
{ {
if (s->physical_offset != s->logical_offset) 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; return -1;
s->physical_offset = s->logical_offset; s->physical_offset = s->logical_offset;
} }
...@@ -1025,7 +1055,7 @@ fd_to_stream (int fd, bool unformatted) ...@@ -1025,7 +1055,7 @@ fd_to_stream (int fd, bool unformatted)
/* Get the current length of the file. */ /* 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->st_dev = s->st_ino = -1;
s->file_length = 0; s->file_length = 0;
...@@ -1134,9 +1164,9 @@ tempfile_open (const char *tempdir, char **fname) ...@@ -1134,9 +1164,9 @@ tempfile_open (const char *tempdir, char **fname)
#endif #endif
#if defined(HAVE_MKOSTEMP) && defined(O_CLOEXEC) #if defined(HAVE_MKOSTEMP) && defined(O_CLOEXEC)
fd = mkostemp (template, O_CLOEXEC); TEMP_FAILURE_RETRY (fd = mkostemp (template, O_CLOEXEC));
#else #else
fd = mkstemp (template); TEMP_FAILURE_RETRY (fd = mkstemp (template));
set_close_on_exec (fd); set_close_on_exec (fd);
#endif #endif
...@@ -1178,7 +1208,7 @@ tempfile_open (const char *tempdir, char **fname) ...@@ -1178,7 +1208,7 @@ tempfile_open (const char *tempdir, char **fname)
continue; 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); while (fd == -1 && errno == EEXIST);
#ifndef O_CLOEXEC #ifndef O_CLOEXEC
...@@ -1355,7 +1385,7 @@ regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags) ...@@ -1355,7 +1385,7 @@ regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags)
#endif #endif
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; 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) if (flags->action != ACTION_UNSPECIFIED)
return fd; return fd;
...@@ -1373,7 +1403,7 @@ regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags) ...@@ -1373,7 +1403,7 @@ regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags)
crflag2 = crflag & ~(O_CREAT); crflag2 = crflag & ~(O_CREAT);
else else
crflag2 = crflag; crflag2 = crflag;
fd = open (path, rwflag | crflag2, mode); TEMP_FAILURE_RETRY (fd = open (path, rwflag | crflag2, mode));
if (fd >=0) if (fd >=0)
{ {
flags->action = ACTION_READ; flags->action = ACTION_READ;
...@@ -1385,7 +1415,7 @@ regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags) ...@@ -1385,7 +1415,7 @@ regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags)
/* retry for write-only access */ /* retry for write-only access */
rwflag = O_WRONLY; rwflag = O_WRONLY;
fd = open (path, rwflag | crflag, mode); TEMP_FAILURE_RETRY (fd = open (path, rwflag | crflag, mode));
if (fd >=0) if (fd >=0)
{ {
flags->action = ACTION_WRITE; flags->action = ACTION_WRITE;
...@@ -1512,7 +1542,7 @@ compare_file_filename (gfc_unit *u, const char *name, int len) ...@@ -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 /* If the filename doesn't exist, then there is no match with the
* existing file. */ * existing file. */
if (stat (path, &st) < 0) if (TEMP_FAILURE_RETRY (stat (path, &st)) < 0)
{ {
ret = 0; ret = 0;
goto done; goto done;
...@@ -1614,7 +1644,7 @@ find_file (const char *file, gfc_charlen_type file_len) ...@@ -1614,7 +1644,7 @@ find_file (const char *file, gfc_charlen_type file_len)
char *path = fc_strdup (file, 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; u = NULL;
goto done; goto done;
...@@ -1742,7 +1772,8 @@ file_size (const char *file, gfc_charlen_type file_len) ...@@ -1742,7 +1772,8 @@ file_size (const char *file, gfc_charlen_type file_len)
{ {
char *path = fc_strdup (file, file_len); char *path = fc_strdup (file, file_len);
struct stat statbuf; struct stat statbuf;
int err = stat (path, &statbuf); int err;
TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
free (path); free (path);
if (err == -1) if (err == -1)
return -1; return -1;
...@@ -1764,7 +1795,8 @@ inquire_sequential (const char *string, int len) ...@@ -1764,7 +1795,8 @@ inquire_sequential (const char *string, int len)
return unknown; return unknown;
char *path = fc_strdup (string, len); char *path = fc_strdup (string, len);
int err = stat (path, &statbuf); int err;
TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
free (path); free (path);
if (err == -1) if (err == -1)
return unknown; return unknown;
...@@ -1792,7 +1824,8 @@ inquire_direct (const char *string, int len) ...@@ -1792,7 +1824,8 @@ inquire_direct (const char *string, int len)
return unknown; return unknown;
char *path = fc_strdup (string, len); char *path = fc_strdup (string, len);
int err = stat (path, &statbuf); int err;
TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
free (path); free (path);
if (err == -1) if (err == -1)
return unknown; return unknown;
...@@ -1820,7 +1853,8 @@ inquire_formatted (const char *string, int len) ...@@ -1820,7 +1853,8 @@ inquire_formatted (const char *string, int len)
return unknown; return unknown;
char *path = fc_strdup (string, len); char *path = fc_strdup (string, len);
int err = stat (path, &statbuf); int err;
TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
free (path); free (path);
if (err == -1) if (err == -1)
return unknown; return unknown;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment