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");