mirror of git://gcc.gnu.org/git/gcc.git
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
|
|
@ -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…
Reference in New Issue