diff libfdcore/sctp.c @ 1200:ce2b00dc86c1

React quickly to head-of-the-line blocking in case of network failure. Can be adapted with MAX_HOTL_BLOCKING_TIME constant in cnxctx.h
author Sebastien Decugis <sdecugis@freediameter.net>
date Fri, 14 Jun 2013 10:14:11 +0800
parents 8c4dd4b693c6
children e5010975da35
line wrap: on
line diff
--- a/libfdcore/sctp.c	Fri Jun 14 10:13:22 2013 +0800
+++ b/libfdcore/sctp.c	Fri Jun 14 10:14:11 2013 +0800
@@ -1083,10 +1083,11 @@
 	uint8_t anci[CMSG_SPACE(sizeof(struct sctp_sndinfo))];	
 #endif /* OLD_SCTP_SOCKET_API */
 	ssize_t ret;
-	int timedout = 0;
+	struct timespec ts, now;
 	
 	TRACE_ENTRY("%p %hu %p %d", conn, strid, iov, iovcnt);
 	CHECK_PARAMS_DO(conn && iov && iovcnt, { errno = EINVAL; return -1; } );
+	CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &ts), return -1 );
 	
 	memset(&mhdr, 0, sizeof(mhdr));
 	memset(&anci, 0, sizeof(anci));
@@ -1120,12 +1121,17 @@
 	/* Handle special case of timeout */
 	if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) {
 		pthread_testcancel();
-		if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING ))
+		/* Check how much time we were blocked for this sending. */
+		CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &now), return -1 );
+		if ( ((now.tv_sec - ts.tv_sec) * 1000 + ((now.tv_nsec - ts.tv_nsec) / 1000000L)) > MAX_HOTL_BLOCKING_TIME) {
+			LOG_D("Unable to send any data for %dms, closing the connection", MAX_HOTL_BLOCKING_TIME);
+		} else if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING )) {
 			goto again; /* don't care, just ignore */
-		if (!timedout) {
-			timedout ++; /* allow for one timeout while closing */
-			goto again;
 		}
+		
+		/* propagate the error */
+		errno = -ret;
+		ret = -1;
 	}
 	
 	CHECK_SYS_DO( ret, ); /* for tracing error only */
"Welcome to our mercurial repository"