]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: istream-file/unix - don't ignore EINTR for blocking istream reads
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 4 Oct 2017 12:08:07 +0000 (15:08 +0300)
committerTimo Sirainen <tss@dovecot.fi>
Thu, 5 Oct 2017 08:20:49 +0000 (11:20 +0300)
Just fail the istream read entirely. Although there's a small possibility
that this interrupt was unwanted and should be retried, it's more likely
that a blocking istream is hanging and admin wants to stop the process.
If the EINTR is ignored all the time, it's not possible to abort a
blocking read with ^C or anything else than SIGKILL.

src/lib/istream-file.c
src/lib/istream-unix.c

index a15af40b136dc7b1f329a3aea74cf39e989ed123..e002146c21a3fe0c56fce6f1419380999d48552c 100644 (file)
@@ -58,20 +58,18 @@ ssize_t i_stream_file_read(struct istream_private *stream)
        }
 
        offset = stream->istream.v_offset + (stream->pos - stream->skip);
-       do {
-               if (fstream->file) {
-                       ret = pread(stream->fd, stream->w_buffer + stream->pos,
-                                   size, offset);
-               } else if (fstream->seen_eof) {
-                       /* don't try to read() again. EOF from keyboard (^D)
-                          requires this to work right. */
-                       ret = 0;
-               } else {
-                       ret = read(stream->fd, stream->w_buffer + stream->pos,
-                                  size);
-               }
-       } while (unlikely(ret < 0 && errno == EINTR &&
-                         stream->istream.blocking));
+
+       if (fstream->file) {
+               ret = pread(stream->fd, stream->w_buffer + stream->pos,
+                           size, offset);
+       } else if (fstream->seen_eof) {
+               /* don't try to read() again. EOF from keyboard (^D)
+                  requires this to work right. */
+               ret = 0;
+       } else {
+               ret = read(stream->fd, stream->w_buffer + stream->pos,
+                          size);
+       }
 
        if (ret == 0) {
                /* EOF */
@@ -81,8 +79,8 @@ ssize_t i_stream_file_read(struct istream_private *stream)
        }
 
        if (unlikely(ret < 0)) {
-               if (errno == EINTR || errno == EAGAIN) {
-                       i_assert(!stream->istream.blocking);
+               if ((errno == EINTR || errno == EAGAIN) &&
+                   !stream->istream.blocking) {
                        ret = 0;
                } else {
                        i_assert(errno != 0);
index 3d79bedf9c6cd9c4554807fdd500c4bbb4d2d4b3..ce9b0195a2fc3c187c1e9ed774062eb18acb7078 100644 (file)
@@ -34,12 +34,8 @@ static ssize_t i_stream_unix_read(struct istream_private *stream)
        if (!i_stream_try_alloc(stream, 1, &size))
                return -2;
 
-       do {
-               ret = fd_read(stream->fd,
-                             stream->w_buffer + stream->pos, size,
-                             &ustream->read_fd);
-       } while (unlikely(ret < 0 && errno == EINTR &&
-                         stream->istream.blocking));
+       ret = fd_read(stream->fd, stream->w_buffer + stream->pos, size,
+                     &ustream->read_fd);
        if (ustream->read_fd != -1)
                ustream->next_read_fd = FALSE;
 
@@ -51,8 +47,8 @@ static ssize_t i_stream_unix_read(struct istream_private *stream)
        }
 
        if (unlikely(ret < 0)) {
-               if (errno == EINTR || errno == EAGAIN) {
-                       i_assert(!stream->istream.blocking);
+               if ((errno == EINTR || errno == EAGAIN) &&
+                   !stream->istream.blocking) {
                        return 0;
                } else {
                        i_assert(errno != 0);