12 #include "pthreadpool_pipe.h"
13 #include "pthreadpool_tevent.h"
15 static int test_init(void)
17 struct pthreadpool_pipe *p;
20 ret = pthreadpool_pipe_init(1, &p);
22 fprintf(stderr, "pthreadpool_pipe_init failed: %s\n",
26 ret = pthreadpool_pipe_destroy(p);
28 fprintf(stderr, "pthreadpool_pipe_destroy failed: %s\n",
35 static void test_sleep(void *ptr)
37 int *ptimeout = (int *)ptr;
39 ret = poll(NULL, 0, *ptimeout);
41 fprintf(stderr, "poll returned %d (%s)\n",
42 ret, strerror(errno));
46 static int test_jobs(int num_threads, int num_jobs)
49 struct pthreadpool_pipe *p;
53 finished = (char *)calloc(1, num_jobs);
54 if (finished == NULL) {
55 fprintf(stderr, "calloc failed\n");
59 ret = pthreadpool_pipe_init(num_threads, &p);
61 fprintf(stderr, "pthreadpool_pipe_init failed: %s\n",
66 for (i=0; i<num_jobs; i++) {
67 ret = pthreadpool_pipe_add_job(p, i, test_sleep, &timeout);
69 fprintf(stderr, "pthreadpool_pipe_add_job failed: "
70 "%s\n", strerror(ret));
75 for (i=0; i<num_jobs; i++) {
77 ret = pthreadpool_pipe_finished_jobs(p, &jobid, 1);
79 fprintf(stderr, "pthreadpool_pipe_finished_jobs "
80 "failed: %s\n", strerror(-ret));
83 if ((ret != 1) || (jobid >= num_jobs)) {
84 fprintf(stderr, "invalid job number %d\n", jobid);
90 for (i=0; i<num_jobs; i++) {
91 if (finished[i] != 1) {
92 fprintf(stderr, "finished[%d] = %d\n",
98 ret = pthreadpool_pipe_destroy(p);
100 fprintf(stderr, "pthreadpool_pipe_destroy failed: %s\n",
109 static int test_busydestroy(void)
111 struct pthreadpool_pipe *p;
116 ret = pthreadpool_pipe_init(1, &p);
118 fprintf(stderr, "pthreadpool_pipe_init failed: %s\n",
122 ret = pthreadpool_pipe_add_job(p, 1, test_sleep, &timeout);
124 fprintf(stderr, "pthreadpool_pipe_add_job failed: %s\n",
128 ret = pthreadpool_pipe_destroy(p);
130 fprintf(stderr, "Could destroy a busy pool\n");
134 pfd.fd = pthreadpool_pipe_signal_fd(p);
135 pfd.events = POLLIN|POLLERR;
138 ret = poll(&pfd, 1, -1);
139 } while ((ret == -1) && (errno == EINTR));
141 ret = pthreadpool_pipe_finished_jobs(p, &jobid, 1);
143 fprintf(stderr, "pthreadpool_pipe_finished_jobs failed: %s\n",
148 ret = pthreadpool_pipe_destroy(p);
150 fprintf(stderr, "pthreadpool_pipe_destroy failed: %s\n",
157 static int test_fork(void)
159 struct pthreadpool_pipe *p;
163 ret = pthreadpool_pipe_init(1, &p);
165 fprintf(stderr, "pthreadpool_pipe_init failed: %s\n",
169 ret = pthreadpool_pipe_destroy(p);
171 fprintf(stderr, "pthreadpool_pipe_destroy failed: %s\n",
178 perror("fork failed");
184 waited = wait(&status);
186 perror("wait failed");
189 if (waited != child) {
190 fprintf(stderr, "expected child %d, got %d\n",
191 (int)child, (int)waited);
197 static void busyfork_job(void *private_data)
202 static int test_busyfork(void)
204 struct pthreadpool_pipe *p;
207 pid_t child, waitret;
208 int ret, jobnum, wstatus;
212 perror("pipe failed");
216 ret = pthreadpool_pipe_init(1, &p);
218 fprintf(stderr, "pthreadpool_pipe_init failed: %s\n",
223 ret = pthreadpool_pipe_add_job(p, 1, busyfork_job, NULL);
225 fprintf(stderr, "pthreadpool_add_job failed: %s\n",
230 ret = pthreadpool_pipe_finished_jobs(p, &jobnum, 1);
232 fprintf(stderr, "pthreadpool_pipe_finished_jobs failed\n");
236 ret = poll(NULL, 0, 200);
238 perror("poll failed");
244 perror("fork failed");
249 ret = pthreadpool_pipe_destroy(p);
251 fprintf(stderr, "pthreadpool_pipe_destroy failed: "
252 "%s\n", strerror(ret));
260 perror("close failed");
264 pfd = (struct pollfd) { .fd = fds[0], .events = POLLIN };
266 ret = poll(&pfd, 1, 5000);
268 perror("poll failed");
272 fprintf(stderr, "Child did not exit for 5 seconds\n");
274 * The child might hang forever in
275 * pthread_cond_destroy for example. Be kind to the
276 * system and kill it.
278 kill(child, SIGTERM);
282 fprintf(stderr, "poll returned %d -- huh??\n", ret);
286 ret = poll(NULL, 0, 200);
288 perror("poll failed");
292 waitret = waitpid(child, &wstatus, WNOHANG);
293 if (waitret != child) {
294 fprintf(stderr, "waitpid returned %d\n", (int)waitret);
298 if (!WIFEXITED(wstatus)) {
299 fprintf(stderr, "child did not properly exit\n");
303 ret = WEXITSTATUS(wstatus);
305 fprintf(stderr, "child returned %d\n", ret);
312 static int test_busyfork2(void)
314 struct pthreadpool_pipe *p;
319 ret = pthreadpool_pipe_init(1, &p);
321 fprintf(stderr, "pthreadpool_pipe_init failed: %s\n",
326 ret = pthreadpool_pipe_add_job(p, 1, busyfork_job, NULL);
328 fprintf(stderr, "pthreadpool_add_job failed: %s\n",
333 ret = pthreadpool_pipe_finished_jobs(p, &jobnum, 1);
335 fprintf(stderr, "pthreadpool_pipe_finished_jobs failed\n");
339 ret = poll(NULL, 0, 10);
341 perror("poll failed");
345 ret = pthreadpool_pipe_add_job(p, 1, busyfork_job, NULL);
347 fprintf(stderr, "pthreadpool_add_job failed: %s\n",
353 * Do the fork right after the add_job. This tests a race
354 * where the atfork prepare handler gets all idle threads off
355 * the condvar. If we are faster doing the fork than the
356 * existing idle thread could get out of idle and take the
357 * job, after the fork we end up with no threads to take care
363 perror("fork failed");
371 pfd = (struct pollfd) {
372 .fd = pthreadpool_pipe_signal_fd(p),
373 .events = POLLIN|POLLERR
377 ret = poll(&pfd, 1, 5000);
378 } while ((ret == -1) && (errno == EINTR));
381 fprintf(stderr, "job unfinished after 5 seconds\n");
388 static void test_tevent_wait(void *private_data)
390 int *timeout = private_data;
391 poll(NULL, 0, *timeout);
394 static int test_tevent_1(void)
396 struct tevent_context *ev;
397 struct pthreadpool_tevent *pool;
398 struct tevent_req *req1, *req2;
400 int timeout100 = 100;
404 ev = tevent_context_init(NULL);
407 fprintf(stderr, "tevent_context_init failed: %s\n",
411 ret = pthreadpool_tevent_init(ev, UINT_MAX, &pool);
413 fprintf(stderr, "pthreadpool_tevent_init failed: %s\n",
418 req1 = pthreadpool_tevent_job_send(
419 ev, ev, pool, test_tevent_wait, &timeout10);
421 fprintf(stderr, "pthreadpool_tevent_job_send failed\n");
425 req2 = pthreadpool_tevent_job_send(
426 ev, ev, pool, test_tevent_wait, &timeout100);
428 fprintf(stderr, "pthreadpool_tevent_job_send failed\n");
432 ok = tevent_req_poll(req2, ev);
435 fprintf(stderr, "tevent_req_poll failed: %s\n",
440 ret = pthreadpool_tevent_job_recv(req1);
443 fprintf(stderr, "tevent_req_poll failed: %s\n",
451 ret = tevent_loop_wait(ev);
453 fprintf(stderr, "tevent_loop_wait failed\n");
466 ret = test_tevent_1();
468 fprintf(stderr, "test_event_1 failed: %s\n",
475 fprintf(stderr, "test_init failed\n");
481 fprintf(stderr, "test_fork failed\n");
485 ret = test_jobs(10, 10000);
487 fprintf(stderr, "test_jobs failed\n");
491 ret = test_busydestroy();
493 fprintf(stderr, "test_busydestroy failed\n");
497 ret = test_busyfork();
499 fprintf(stderr, "test_busyfork failed\n");
503 ret = test_busyfork2();
505 fprintf(stderr, "test_busyfork2 failed\n");