From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 109324 invoked by alias); 9 Oct 2016 13:59:15 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 109292 invoked by uid 89); 9 Oct 2016 13:59:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.0 required=5.0 tests=AWL,BAYES_50,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_SPAM,SPF_PASS autolearn=no version=3.3.2 spammy=5187, jb@gcc.gnu.org, jbgccgnuorg, U*jb X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-lf0-f42.google.com Received: from mail-lf0-f42.google.com (HELO mail-lf0-f42.google.com) (209.85.215.42) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 09 Oct 2016 13:59:04 +0000 Received: by mail-lf0-f42.google.com with SMTP id b75so76330258lfg.3; Sun, 09 Oct 2016 06:59:03 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version; bh=/TDOqlrPSguZmnpsHkRzbqvO7jGUoPivO2ong0qkfrY=; b=MuioMBbDxHlt05HKWaBafJkHmv8hu1JKmc26YZWFVI3/HTDFFKCzw66U1uzdqxqGyf /fFu0IwHDoEows3pxN0s4ze10irPkLuXz2NOb6L9/iuiRlnryeJPVj8hIpS3RrMEtYNC QjbOCaf/qBy1l4mfPFYwnPEwBiG9Vvan1oqRCW7EsAFDxM8tEN3qxQNZdQ4lH2uuTRFz rSQVH/DXk4wHAsDx5+ER643N3e5QNN1CeQuWTye5XYO9Kz3sXbaidSCfGLkOEb4C7xjC /+nKcC4SEs1elNqPjEMyKsKuI6OlHlz2AJ1PrbP/dyD8fxkTZjN5bpizHL8tiB7jL7Ri ODmQ== X-Gm-Message-State: AA6/9RkvqCWDJ/F7h1mmfUVRe9DfchPEbpfUrzjtlf4yMKNJ10Q/gpWQ56PWjBUwbxiNPw== X-Received: by 10.25.18.97 with SMTP id h94mr11849020lfi.106.1476021541530; Sun, 09 Oct 2016 06:59:01 -0700 (PDT) Received: from dt.lan (91-159-207-203.elisa-laajakaista.fi. [91.159.207.203]) by smtp.gmail.com with ESMTPSA id h68sm5114339lji.20.2016.10.09.06.58.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 09 Oct 2016 06:59:00 -0700 (PDT) From: Janne Blomqvist To: fortran@gcc.gnu.org, gcc-patches@gcc.gnu.org Cc: Janne Blomqvist Subject: [PATCH] PR 67585 Handle EINTR Date: Sun, 09 Oct 2016 13:59:00 -0000 Message-Id: <1476021521-16095-1-git-send-email-blomqvist.janne@gmail.com> In-Reply-To: <1475843186-3429-1-git-send-email-blomqvist.janne@gmail.com> References: <1475843186-3429-1-git-send-email-blomqvist.janne@gmail.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------2.7.4" X-SW-Source: 2016-10/txt/msg00558.txt.bz2 This is a multi-part message in MIME format. --------------2.7.4 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit Content-length: 1295 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 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): Likewise. (tempfile_open): Likewise. (regular_file2): Likewise. (compare_file_filename): Likewise. (find_file): Likewise. (inquire_sequential): Likewise. (inquire_direct): Likewise. (inquire_formatted): Likewise. Version 2 of the patch: Use the TEMP_FAILURE_RETRY macro to do the EINTR loop when appropriate, cover more functions (open, mk(o)stemp, (f)stat). Regtested on x86_64-pc-linux-gnu. Ok for trunk? --- libgfortran/io/io.h | 15 +++++++++ libgfortran/io/unix.c | 86 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 75 insertions(+), 26 deletions(-) --------------2.7.4 Content-Type: text/x-patch; name="0001-PR-67585-Handle-EINTR.patch" Content-Transfer-Encoding: 8bit Content-Disposition: attachment; filename="0001-PR-67585-Handle-EINTR.patch" Content-length: 8451 diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h index ff75741..c8b9bc6 100644 --- a/libgfortran/io/io.h +++ b/libgfortran/io/io.h @@ -647,6 +647,21 @@ typedef struct gfc_unit gfc_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. */ diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c index 29818cd..1e84c42 100644 --- a/libgfortran/io/unix.c +++ b/libgfortran/io/unix.c @@ -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; --------------2.7.4--