Hi,

I spotted that tests 502, 555, and 573 do not call select() when looping 
around curl_multi_perform().  Is that intentionally?

We have been observing random timout events on 555 and 573 when running 
through valgrind on our overloaded virtualized Fedora build hosts.  Adding 
select() to those tests seems to solve (or at least suppress) the problem.

A tentative patch is attached.

Kamil
From d5952e46bd2e5f02a2be952b0a0b65324e376596 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <[email protected]>
Date: Fri, 26 Aug 2011 11:10:58 +0200
Subject: [PATCH] tests: break busy loops in tests 502, 555, and 573

---
 tests/libtest/lib502.c |   20 ++++++++++++++++++++
 tests/libtest/lib555.c |   20 ++++++++++++++++++++
 tests/libtest/lib573.c |   20 ++++++++++++++++++++
 3 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/tests/libtest/lib502.c b/tests/libtest/lib502.c
index 9ade12a..d936a44 100644
--- a/tests/libtest/lib502.c
+++ b/tests/libtest/lib502.c
@@ -73,6 +73,10 @@ int test(char *URL)
   mp_start = tutil_tvnow();
 
   while (running) {
+    static struct timeval timeout = /* 100 ms */ { 0, 100000L };
+    fd_set fdread, fdwrite, fdexcep;
+    int maxfd = -1;
+
     res = (int)curl_multi_perform(m, &running);
     if (tutil_tvdiff(tutil_tvnow(), mp_start) >
         MULTI_PERFORM_HANG_TIMEOUT) {
@@ -83,6 +87,22 @@ int test(char *URL)
       fprintf(stderr, "nothing left running.\n");
       break;
     }
+
+    FD_ZERO(&fdread);
+    FD_ZERO(&fdwrite);
+    FD_ZERO(&fdexcep);
+    curl_multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);
+
+    /* In a real-world program you OF COURSE check the return code of the
+       function calls.  On success, the value of maxfd is guaranteed to be
+       greater or equal than -1.  We call select(maxfd + 1, ...), specially in
+       case of (maxfd == -1), we call select(0, ...), which is basically equal
+       to sleep. */
+
+    if (select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout) == -1) {
+      res = ~CURLM_OK;
+      break;
+    }
   }
 
   if (mp_timedout) {
diff --git a/tests/libtest/lib555.c b/tests/libtest/lib555.c
index c675015..5d10771 100644
--- a/tests/libtest/lib555.c
+++ b/tests/libtest/lib555.c
@@ -135,6 +135,10 @@ int test(char *URL)
   mp_start = tutil_tvnow();
 
   while (running) {
+    static struct timeval timeout = /* 100 ms */ { 0, 100000L };
+    fd_set fdread, fdwrite, fdexcep;
+    int maxfd = -1;
+
     res = (int)curl_multi_perform(m, &running);
     if (tutil_tvdiff(tutil_tvnow(), mp_start) >
         MULTI_PERFORM_HANG_TIMEOUT) {
@@ -148,6 +152,22 @@ int test(char *URL)
       fprintf(stderr, "nothing left running.\n");
       break;
     }
+
+    FD_ZERO(&fdread);
+    FD_ZERO(&fdwrite);
+    FD_ZERO(&fdexcep);
+    curl_multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);
+
+    /* In a real-world program you OF COURSE check the return code of the
+       function calls.  On success, the value of maxfd is guaranteed to be
+       greater or equal than -1.  We call select(maxfd + 1, ...), specially in
+       case of (maxfd == -1), we call select(0, ...), which is basically equal
+       to sleep. */
+
+    if (select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout) == -1) {
+      res = ~CURLM_OK;
+      break;
+    }
   }
 
   if (mp_timedout) {
diff --git a/tests/libtest/lib573.c b/tests/libtest/lib573.c
index 4661858..79b22dd 100644
--- a/tests/libtest/lib573.c
+++ b/tests/libtest/lib573.c
@@ -76,6 +76,10 @@ int test(char *URL)
   mp_start = tutil_tvnow();
 
   while (running) {
+    static struct timeval timeout = /* 100 ms */ { 0, 100000L };
+    fd_set fdread, fdwrite, fdexcep;
+    int maxfd = -1;
+
     res = (int)curl_multi_perform(m, &running);
     if (tutil_tvdiff(tutil_tvnow(), mp_start) >
         MULTI_PERFORM_HANG_TIMEOUT) {
@@ -86,6 +90,22 @@ int test(char *URL)
       fprintf(stderr, "nothing left running.\n");
       break;
     }
+
+    FD_ZERO(&fdread);
+    FD_ZERO(&fdwrite);
+    FD_ZERO(&fdexcep);
+    curl_multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);
+
+    /* In a real-world program you OF COURSE check the return code of the
+       function calls.  On success, the value of maxfd is guaranteed to be
+       greater or equal than -1.  We call select(maxfd + 1, ...), specially in
+       case of (maxfd == -1), we call select(0, ...), which is basically equal
+       to sleep. */
+
+    if (select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout) == -1) {
+      res = ~CURLM_OK;
+      break;
+    }
   }
 
   if (mp_timedout) {
-- 
1.7.4.4

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Reply via email to