diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2016-04-23 20:20:09 +0000 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2016-04-23 20:20:09 +0000 |
commit | 61ad888a7be9be0b14e2f3f648ba9b6e6d2808d6 (patch) | |
tree | 83c97d96f1bd2d92ed1205df390e208992508d12 | |
parent | e275dc739830aa1a01503348fff04ccc5258f42c (diff) | |
download | libmicrohttpd-61ad888a7be9be0b14e2f3f648ba9b6e6d2808d6.tar.gz libmicrohttpd-61ad888a7be9be0b14e2f3f648ba9b6e6d2808d6.zip |
perf_get_concurrent: port to systems without fork(), added error checking
-rw-r--r-- | src/testcurl/Makefile.am | 10 | ||||
-rw-r--r-- | src/testcurl/perf_get_concurrent.c | 176 |
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 | ||
19 | if !HAVE_W32 | 19 | if !HAVE_W32 |
20 | PERF_GET_CONCURRENT=perf_get_concurrent | ||
21 | TEST_CONCURRENT_STOP=test_concurrent_stop | 20 | TEST_CONCURRENT_STOP=test_concurrent_stop |
22 | if HAVE_CURL_BINARY | 21 | if HAVE_CURL_BINARY |
23 | CURL_FORK_TEST = test_get_response_cleanup | 22 | CURL_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 | ||
54 | if HAVE_POSIX_THREADS | 53 | if HAVE_POSIX_THREADS |
55 | check_PROGRAMS += \ | 54 | check_PROGRAMS += \ |
56 | test_quiesce | 55 | test_quiesce \ |
56 | perf_get_concurrent | ||
57 | endif | 57 | endif |
58 | 58 | ||
59 | if HAVE_POSTPROCESSOR | 59 | if HAVE_POSTPROCESSOR |
@@ -128,9 +128,11 @@ perf_get_LDADD = \ | |||
128 | perf_get_concurrent_SOURCES = \ | 128 | perf_get_concurrent_SOURCES = \ |
129 | perf_get_concurrent.c \ | 129 | perf_get_concurrent.c \ |
130 | gauger.h | 130 | gauger.h |
131 | perf_get_concurrent_CFLAGS = \ | ||
132 | $(PTHREAD_CFLAGS) $(AM_CFLAGS) | ||
131 | perf_get_concurrent_LDADD = \ | 133 | perf_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 | ||
135 | test_digestauth_SOURCES = \ | 137 | test_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 | 162 | static void * | |
162 | static pid_t | 163 | thread_gets (void *param) |
163 | do_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, ©Buffer); | ||
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 | |||
201 | static void * | ||
202 | do_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, ©Buffer); | ||
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; | |
220 | static void | 227 | } |
221 | join_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 | |||
233 | testInternalGet (int port, int poll_flag) | 233 | testInternalGet (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 | |||
250 | testMultithreadedGet (int port, int poll_flag) | 259 | testMultithreadedGet (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 | |||
266 | testMultithreadedPoolGet (int port, int poll_flag) | 284 | testMultithreadedPoolGet (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 | |||
283 | testExternalGet (int port) | 310 | testExternalGet (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 | ||