changeset 18921:c143d037fd54

lib: istream-timeout could have triggered timeout too early after long-running code.
author Timo Sirainen <tss@iki.fi>
date Fri, 07 Aug 2015 12:58:30 +0300
parents 35d3777cc4d2
children 91005181b997
files src/lib/istream-timeout.c
diffstat 1 files changed, 20 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/istream-timeout.c	Fri Aug 07 11:31:29 2015 +0300
+++ b/src/lib/istream-timeout.c	Fri Aug 07 12:58:30 2015 +0300
@@ -41,6 +41,13 @@
 	unsigned int msecs;
 	int diff;
 
+	if (tstream->update_timestamp) {
+		/* we came here after a long-running code. timeouts are handled
+		   before IOs, so wait for i_stream_read() to be called again
+		   before assuming that we've timed out. */
+		return;
+	}
+
 	timeout_remove(&tstream->to);
 
 	diff = timeval_diff_msecs(&ioloop_timeval, &tstream->last_read_timestamp);
@@ -64,6 +71,17 @@
 	i_stream_set_input_pending(tstream->istream.parent, TRUE);
 }
 
+static void i_stream_timeout_set_pending(struct timeout_istream *tstream)
+{
+	/* make sure we get called again on the next ioloop run. this updates
+	   the timeout to the timestamp where we actually would have wanted to
+	   start waiting for more data (so if there is long-running code
+	   outside the ioloop it's not counted) */
+	tstream->update_timestamp = TRUE;
+	tstream->last_read_timestamp = ioloop_timeval;
+	i_stream_set_input_pending(&tstream->istream.istream, TRUE);
+}
+
 static ssize_t
 i_stream_timeout_read(struct istream_private *stream)
 {
@@ -90,19 +108,11 @@
 		tstream->to = tstream->timeout_msecs == 0 ? NULL :
 			timeout_add(tstream->timeout_msecs,
 				    i_stream_timeout, tstream);
-		tstream->update_timestamp = TRUE;
-		tstream->last_read_timestamp = ioloop_timeval;
+		i_stream_timeout_set_pending(tstream);
 	} else if (ret > 0 && tstream->to != NULL) {
 		/* we read something, reset the timeout */
 		timeout_reset(tstream->to);
-		/* make sure we get called again on the next ioloop run.
-		   this updates the timeout to the timestamp where we actually
-		   would have wanted to start waiting for more data (so if
-		   there is long-running code outside the ioloop it's not
-		   counted) */
-		tstream->update_timestamp = TRUE;
-		tstream->last_read_timestamp = ioloop_timeval;
-		i_stream_set_input_pending(&stream->istream, TRUE);
+		i_stream_timeout_set_pending(tstream);
 	} else if (tstream->update_timestamp) {
 		tstream->update_timestamp = FALSE;
 		tstream->last_read_timestamp = ioloop_timeval;