aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2016-04-23 20:20:09 +0000
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2016-04-23 20:20:09 +0000
commit61ad888a7be9be0b14e2f3f648ba9b6e6d2808d6 (patch)
tree83c97d96f1bd2d92ed1205df390e208992508d12
parente275dc739830aa1a01503348fff04ccc5258f42c (diff)
downloadlibmicrohttpd-61ad888a7be9be0b14e2f3f648ba9b6e6d2808d6.tar.gz
libmicrohttpd-61ad888a7be9be0b14e2f3f648ba9b6e6d2808d6.zip
perf_get_concurrent: port to systems without fork(), added error checking
-rw-r--r--src/testcurl/Makefile.am10
-rw-r--r--src/testcurl/perf_get_concurrent.c176
2 files changed, 116 insertions, 70 deletions
diff --git a/src/testcurl/Makefile.am b/src/testcurl/Makefile.am
index eb165bd4..510516c3 100644
--- a/src/testcurl/Makefile.am
+++ b/src/testcurl/Makefile.am
@@ -17,7 +17,6 @@ AM_CPPFLAGS = \
17$(LIBCURL_CPPFLAGS) 17$(LIBCURL_CPPFLAGS)
18 18
19if !HAVE_W32 19if !HAVE_W32
20PERF_GET_CONCURRENT=perf_get_concurrent
21TEST_CONCURRENT_STOP=test_concurrent_stop 20TEST_CONCURRENT_STOP=test_concurrent_stop
22if HAVE_CURL_BINARY 21if HAVE_CURL_BINARY
23CURL_FORK_TEST = test_get_response_cleanup 22CURL_FORK_TEST = test_get_response_cleanup
@@ -49,11 +48,12 @@ check_PROGRAMS = \
49 test_timeout \ 48 test_timeout \
50 test_callback \ 49 test_callback \
51 $(CURL_FORK_TEST) \ 50 $(CURL_FORK_TEST) \
52 perf_get $(PERF_GET_CONCURRENT) 51 perf_get
53 52
54if HAVE_POSIX_THREADS 53if HAVE_POSIX_THREADS
55check_PROGRAMS += \ 54check_PROGRAMS += \
56 test_quiesce 55 test_quiesce \
56 perf_get_concurrent
57endif 57endif
58 58
59if HAVE_POSTPROCESSOR 59if HAVE_POSTPROCESSOR
@@ -128,9 +128,11 @@ perf_get_LDADD = \
128perf_get_concurrent_SOURCES = \ 128perf_get_concurrent_SOURCES = \
129 perf_get_concurrent.c \ 129 perf_get_concurrent.c \
130 gauger.h 130 gauger.h
131perf_get_concurrent_CFLAGS = \
132 $(PTHREAD_CFLAGS) $(AM_CFLAGS)
131perf_get_concurrent_LDADD = \ 133perf_get_concurrent_LDADD = \
132 $(top_builddir)/src/microhttpd/libmicrohttpd.la \ 134 $(top_builddir)/src/microhttpd/libmicrohttpd.la \
133 @LIBCURL@ 135 $(PTHREAD_LIBS) @LIBCURL@
134 136
135test_digestauth_SOURCES = \ 137test_digestauth_SOURCES = \
136 test_digestauth.c 138 test_digestauth.c
diff --git a/src/testcurl/perf_get_concurrent.c b/src/testcurl/perf_get_concurrent.c
index ee3717f0..5202729c 100644
--- a/src/testcurl/perf_get_concurrent.c
+++ b/src/testcurl/perf_get_concurrent.c
@@ -39,6 +39,7 @@
39#include <stdlib.h> 39#include <stdlib.h>
40#include <string.h> 40#include <string.h>
41#include <time.h> 41#include <time.h>
42#include <pthread.h>
42#include "gauger.h" 43#include "gauger.h"
43 44
44#if defined(CPU_COUNT) && (CPU_COUNT+0) < 2 45#if defined(CPU_COUNT) && (CPU_COUNT+0) < 2
@@ -158,74 +159,73 @@ ahc_echo (void *cls,
158 return ret; 159 return ret;
159} 160}
160 161
161 162static void *
162static pid_t 163thread_gets (void *param)
163do_gets (int port)
164{ 164{
165 pid_t ret;
166 CURL *c; 165 CURL *c;
167 CURLcode errornum; 166 CURLcode errornum;
168 unsigned int i; 167 unsigned int i;
168 char * const url = (char*) param;
169
170 for (i=0;i<ROUNDS;i++)
171 {
172 c = curl_easy_init ();
173 curl_easy_setopt (c, CURLOPT_URL, url);
174 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
175 curl_easy_setopt (c, CURLOPT_WRITEDATA, NULL);
176 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
177 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
178 if (oneone)
179 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
180 else
181 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
182 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
183 /* NOTE: use of CONNECTTIMEOUT without also
184 setting NOSIGNAL results in really weird
185 crashes on my system! */
186 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
187 if (CURLE_OK != (errornum = curl_easy_perform (c)))
188 {
189 fprintf (stderr,
190 "curl_easy_perform failed: `%s'\n",
191 curl_easy_strerror (errornum));
192 curl_easy_cleanup (c);
193 return "curl error";
194 }
195 curl_easy_cleanup (c);
196 }
197
198 return NULL;
199}
200
201static void *
202do_gets (void * param)
203{
169 unsigned int j; 204 unsigned int j;
170 pid_t par[PAR]; 205 pthread_t par[PAR];
171 char url[64]; 206 char url[64];
207 int port = (int)(intptr_t)param;
208 char *err = NULL;
172 209
173 sprintf(url, "http://127.0.0.1:%d/hello_world", port); 210 sprintf(url, "http://127.0.0.1:%d/hello_world", port);
174 211
175 ret = fork ();
176 if (ret == -1) abort ();
177 if (ret != 0)
178 return ret;
179 for (j=0;j<PAR;j++) 212 for (j=0;j<PAR;j++)
180 { 213 {
181 par[j] = fork (); 214 if (0 != pthread_create(&par[j], NULL, &thread_gets, (void*)url))
182 if (par[j] == 0) 215 {
183 { 216 for (j--; j >= 0; j--)
184 for (i=0;i<ROUNDS;i++) 217 pthread_join(par[j], NULL);
185 { 218 return "pthread_create error";
186 c = curl_easy_init (); 219 }
187 curl_easy_setopt (c, CURLOPT_URL, url);
188 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
189 curl_easy_setopt (c, CURLOPT_WRITEDATA, NULL);
190 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
191 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
192 if (oneone)
193 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
194 else
195 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
196 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
197 /* NOTE: use of CONNECTTIMEOUT without also
198 setting NOSIGNAL results in really weird
199 crashes on my system! */
200 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
201 if (CURLE_OK != (errornum = curl_easy_perform (c)))
202 {
203 fprintf (stderr,
204 "curl_easy_perform failed: `%s'\n",
205 curl_easy_strerror (errornum));
206 curl_easy_cleanup (c);
207 _exit (1);
208 }
209 curl_easy_cleanup (c);
210 }
211 _exit (0);
212 }
213 } 220 }
214 for (j=0;j<PAR;j++) 221 for (j=0;j<PAR;j++)
215 waitpid (par[j], NULL, 0); 222 {
216 _exit (0); 223 char *ret_val;
217} 224 if (0 != pthread_join(par[j], (void**)&ret_val) ||
218 225 NULL != ret_val)
219 226 err = ret_val;
220static void 227 }
221join_gets (pid_t pid) 228 return err;
222{
223 int status;
224
225 status = 1;
226 waitpid (pid, &status, 0);
227 if (0 != status)
228 abort ();
229} 229}
230 230
231 231
@@ -233,15 +233,24 @@ static int
233testInternalGet (int port, int poll_flag) 233testInternalGet (int port, int poll_flag)
234{ 234{
235 struct MHD_Daemon *d; 235 struct MHD_Daemon *d;
236 const char * const test_desc = poll_flag ? "internal poll" : "internal select";
237 const char * ret_val;
236 238
237 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG | poll_flag, 239 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG | poll_flag,
238 port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); 240 port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
239 if (d == NULL) 241 if (d == NULL)
240 return 1; 242 return 1;
241 start_timer (); 243 start_timer ();
242 join_gets (do_gets (port)); 244 ret_val = do_gets ((void*)(intptr_t)port);
243 stop (poll_flag ? "internal poll" : "internal select"); 245 if (!ret_val)
246 stop (test_desc);
244 MHD_stop_daemon (d); 247 MHD_stop_daemon (d);
248 if (ret_val)
249 {
250 fprintf (stderr,
251 "Error performing %s test: %s\n", test_desc, ret_val);
252 return 4;
253 }
245 return 0; 254 return 0;
246} 255}
247 256
@@ -250,15 +259,24 @@ static int
250testMultithreadedGet (int port, int poll_flag) 259testMultithreadedGet (int port, int poll_flag)
251{ 260{
252 struct MHD_Daemon *d; 261 struct MHD_Daemon *d;
262 const char * const test_desc = poll_flag ? "thread with poll" : "thread with select";
263 const char * ret_val;
253 264
254 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG | poll_flag, 265 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG | poll_flag,
255 port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); 266 port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
256 if (d == NULL) 267 if (d == NULL)
257 return 16; 268 return 16;
258 start_timer (); 269 start_timer ();
259 join_gets (do_gets (port)); 270 ret_val = do_gets ((void*)(intptr_t)port);
260 stop (poll_flag ? "thread with poll" : "thread with select"); 271 if (!ret_val)
272 stop (test_desc);
261 MHD_stop_daemon (d); 273 MHD_stop_daemon (d);
274 if (ret_val)
275 {
276 fprintf (stderr,
277 "Error performing %s test: %s\n", test_desc, ret_val);
278 return 4;
279 }
262 return 0; 280 return 0;
263} 281}
264 282
@@ -266,6 +284,8 @@ static int
266testMultithreadedPoolGet (int port, int poll_flag) 284testMultithreadedPoolGet (int port, int poll_flag)
267{ 285{
268 struct MHD_Daemon *d; 286 struct MHD_Daemon *d;
287 const char * const test_desc = poll_flag ? "thread pool with poll" : "thread pool with select";
288 const char * ret_val;
269 289
270 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG | poll_flag, 290 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG | poll_flag,
271 port, NULL, NULL, &ahc_echo, "GET", 291 port, NULL, NULL, &ahc_echo, "GET",
@@ -273,9 +293,16 @@ testMultithreadedPoolGet (int port, int poll_flag)
273 if (d == NULL) 293 if (d == NULL)
274 return 16; 294 return 16;
275 start_timer (); 295 start_timer ();
276 join_gets (do_gets (port)); 296 ret_val = do_gets ((void*)(intptr_t)port);
277 stop (poll_flag ? "thread pool with poll" : "thread pool with select"); 297 if (!ret_val)
298 stop (test_desc);
278 MHD_stop_daemon (d); 299 MHD_stop_daemon (d);
300 if (ret_val)
301 {
302 fprintf (stderr,
303 "Error performing %s test: %s\n", test_desc, ret_val);
304 return 4;
305 }
279 return 0; 306 return 0;
280} 307}
281 308
@@ -283,7 +310,7 @@ static int
283testExternalGet (int port) 310testExternalGet (int port)
284{ 311{
285 struct MHD_Daemon *d; 312 struct MHD_Daemon *d;
286 pid_t pid; 313 pthread_t pid;
287 fd_set rs; 314 fd_set rs;
288 fd_set ws; 315 fd_set ws;
289 fd_set es; 316 fd_set es;
@@ -291,14 +318,20 @@ testExternalGet (int port)
291 struct timeval tv; 318 struct timeval tv;
292 MHD_UNSIGNED_LONG_LONG tt; 319 MHD_UNSIGNED_LONG_LONG tt;
293 int tret; 320 int tret;
321 char *ret_val;
322 int ret = 0;
294 323
295 d = MHD_start_daemon (MHD_USE_DEBUG, 324 d = MHD_start_daemon (MHD_USE_DEBUG,
296 port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); 325 port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
297 if (d == NULL) 326 if (d == NULL)
298 return 256; 327 return 256;
328 if (0 != pthread_create(&pid, NULL, &do_gets, (void*)(intptr_t)port))
329 {
330 MHD_stop_daemon(d);
331 return 512;
332 }
299 start_timer (); 333 start_timer ();
300 pid = do_gets (port); 334 while (ESRCH != pthread_kill (pid, 0))
301 while (0 == waitpid (pid, NULL, WNOHANG))
302 { 335 {
303 max = 0; 336 max = 0;
304 FD_ZERO (&rs); 337 FD_ZERO (&rs);
@@ -320,12 +353,23 @@ testExternalGet (int port)
320 fprintf (stderr, 353 fprintf (stderr,
321 "select failed: %s\n", 354 "select failed: %s\n",
322 strerror (errno)); 355 strerror (errno));
356 ret |= 1024;
323 break; 357 break;
324 } 358 }
325 MHD_run (d); 359 MHD_run_from_select(d, &rs, &ws, &es);
326 } 360 }
361
327 stop ("external select"); 362 stop ("external select");
328 MHD_stop_daemon (d); 363 MHD_stop_daemon (d);
364 if (0 != pthread_join(pid, (void**)&ret_val) ||
365 NULL != ret_val)
366 {
367 fprintf (stderr,
368 "%s\n", ret_val);
369 ret |= 8;
370 }
371 if (ret)
372 fprintf (stderr, "Error performing test.\n");
329 return 0; 373 return 0;
330} 374}
331 375