From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 81639 invoked by alias); 7 Oct 2016 12:26:41 -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 81617 invoked by uid 89); 7 Oct 2016 12:26:41 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.4 required=5.0 tests=BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_SPAM,SPF_PASS autolearn=no version=3.3.2 spammy=5187, 409,7, 4097, interrupted X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-lf0-f66.google.com Received: from mail-lf0-f66.google.com (HELO mail-lf0-f66.google.com) (209.85.215.66) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 07 Oct 2016 12:26:30 +0000 Received: by mail-lf0-f66.google.com with SMTP id p80so2587710lfp.1; Fri, 07 Oct 2016 05:26:30 -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:subject:date:message-id; bh=UbJdSWzhmqtr3rvLSXRP1C6QyhtYPZU2He1TqOFv6V8=; b=O+E+IfdquAYtOKN8/Lf9WFlP1Bu3fB30rPjxWmLA204YxwFoiTs4oAtZXgmweXNBaB jIXJYK75VBdr/TFI07bIot+QjF04FZJpeEzprbckulUdGQFAuIUm5ZwU4BagCAb0IpVV puXtZyueJmPOsAeKXn8A5QerVaAs8D/v5eaqcUzsyyX95kMG84VSn7gIWEc1mOP8waa4 ExkefPbBMQVCPyc3FceNSvdWoZWqyZhxijoD0doGvg4Vzl/Lsu16X1FMx0hhpRSjfN6R A6leQSEqyO+sFn1uir4X2dJjv/ZWC06i6Yb2IPssuh7nwrWlXSNkoz9gxo3DzfsSZVLh Z13A== X-Gm-Message-State: AA6/9RnetpFOpUXMTOoDUoIVgGA7+6DVGrJ5/LRhnclBG0FZ1N55AqZtSQ5kM76m58qC6w== X-Received: by 10.25.17.208 with SMTP id 77mr8356330lfr.51.1475843188198; Fri, 07 Oct 2016 05:26:28 -0700 (PDT) Received: from dt.lan (91-159-207-203.elisa-laajakaista.fi. [91.159.207.203]) by smtp.gmail.com with ESMTPSA id 76sm1114695ljb.43.2016.10.07.05.26.27 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 07 Oct 2016 05:26:27 -0700 (PDT) From: Janne Blomqvist To: fortran@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [PATCH, libgfortran] PR 67585 Handle EINTR Date: Fri, 07 Oct 2016 12:26:00 -0000 Message-Id: <1475843186-3429-1-git-send-email-blomqvist.janne@gmail.com> X-SW-Source: 2016-10/txt/msg00481.txt.bz2 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-07 Janne Blomqvist PR libfortran/67585 * 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. Regtested on x86_64-pc-linux-gnu. Ok for trunk? --- libgfortran/io/unix.c | 64 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c index 29818cd..43e33c8 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,37 @@ 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; + while (fstat (s->fd, &statbuf) == -1) + { + if (errno == EINTR) + continue; + return -1; + } if (S_ISREG (statbuf.st_mode)) return statbuf.st_size; else @@ -390,7 +412,13 @@ 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); + while (ftruncate (s->fd, length) == -1) + { + if (errno == EINTR) + continue; + return -1; + } + return 0; #elif defined HAVE_CHSIZE return chsize (s->fd, length); #else @@ -409,7 +437,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 +501,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 +556,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 +625,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; } -- 2.7.4