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",
67 for (i
=0; i
<num_jobs
; i
++) {
68 ret
= pthreadpool_pipe_add_job(p
, i
, test_sleep
, &timeout
);
70 fprintf(stderr
, "pthreadpool_pipe_add_job failed: "
71 "%s\n", strerror(ret
));
77 for (i
=0; i
<num_jobs
; i
++) {
79 ret
= pthreadpool_pipe_finished_jobs(p
, &jobid
, 1);
81 fprintf(stderr
, "pthreadpool_pipe_finished_jobs "
82 "failed: %s\n", strerror(-ret
));
86 if ((ret
!= 1) || (jobid
>= num_jobs
)) {
87 fprintf(stderr
, "invalid job number %d\n", jobid
);
94 for (i
=0; i
<num_jobs
; i
++) {
95 if (finished
[i
] != 1) {
96 fprintf(stderr
, "finished[%d] = %d\n",
103 ret
= pthreadpool_pipe_destroy(p
);
105 fprintf(stderr
, "pthreadpool_pipe_destroy failed: %s\n",
115 static int test_busydestroy(void)
117 struct pthreadpool_pipe
*p
;
122 ret
= pthreadpool_pipe_init(1, &p
);
124 fprintf(stderr
, "pthreadpool_pipe_init failed: %s\n",
128 ret
= pthreadpool_pipe_add_job(p
, 1, test_sleep
, &timeout
);
130 fprintf(stderr
, "pthreadpool_pipe_add_job failed: %s\n",
134 ret
= pthreadpool_pipe_destroy(p
);
136 fprintf(stderr
, "Could destroy a busy pool\n");
140 pfd
.fd
= pthreadpool_pipe_signal_fd(p
);
141 pfd
.events
= POLLIN
|POLLERR
;
144 ret
= poll(&pfd
, 1, -1);
145 } while ((ret
== -1) && (errno
== EINTR
));
147 ret
= pthreadpool_pipe_finished_jobs(p
, &jobid
, 1);
149 fprintf(stderr
, "pthreadpool_pipe_finished_jobs failed: %s\n",
154 ret
= pthreadpool_pipe_destroy(p
);
156 fprintf(stderr
, "pthreadpool_pipe_destroy failed: %s\n",
163 static int test_fork(void)
165 struct pthreadpool_pipe
*p
;
169 ret
= pthreadpool_pipe_init(1, &p
);
171 fprintf(stderr
, "pthreadpool_pipe_init failed: %s\n",
175 ret
= pthreadpool_pipe_destroy(p
);
177 fprintf(stderr
, "pthreadpool_pipe_destroy failed: %s\n",
184 perror("fork failed");
190 waited
= wait(&status
);
192 perror("wait failed");
195 if (waited
!= child
) {
196 fprintf(stderr
, "expected child %d, got %d\n",
197 (int)child
, (int)waited
);
203 static void busyfork_job(void *private_data
)
208 static int test_busyfork(void)
210 struct pthreadpool_pipe
*p
;
213 pid_t child
, waitret
;
214 int ret
, jobnum
, wstatus
;
218 perror("pipe failed");
222 ret
= pthreadpool_pipe_init(1, &p
);
224 fprintf(stderr
, "pthreadpool_pipe_init failed: %s\n",
229 ret
= pthreadpool_pipe_add_job(p
, 1, busyfork_job
, NULL
);
231 fprintf(stderr
, "pthreadpool_add_job failed: %s\n",
236 ret
= pthreadpool_pipe_finished_jobs(p
, &jobnum
, 1);
238 fprintf(stderr
, "pthreadpool_pipe_finished_jobs failed\n");
242 ret
= poll(NULL
, 0, 200);
244 perror("poll failed");
250 perror("fork failed");
255 ret
= pthreadpool_pipe_destroy(p
);
257 fprintf(stderr
, "pthreadpool_pipe_destroy failed: "
258 "%s\n", strerror(ret
));
266 perror("close failed");
270 pfd
= (struct pollfd
) { .fd
= fds
[0], .events
= POLLIN
};
272 ret
= poll(&pfd
, 1, 5000);
274 perror("poll failed");
278 fprintf(stderr
, "Child did not exit for 5 seconds\n");
280 * The child might hang forever in
281 * pthread_cond_destroy for example. Be kind to the
282 * system and kill it.
284 kill(child
, SIGTERM
);
288 fprintf(stderr
, "poll returned %d -- huh??\n", ret
);
292 ret
= poll(NULL
, 0, 200);
294 perror("poll failed");
298 waitret
= waitpid(child
, &wstatus
, WNOHANG
);
299 if (waitret
!= child
) {
300 fprintf(stderr
, "waitpid returned %d\n", (int)waitret
);
304 if (!WIFEXITED(wstatus
)) {
305 fprintf(stderr
, "child did not properly exit\n");
309 ret
= WEXITSTATUS(wstatus
);
311 fprintf(stderr
, "child returned %d\n", ret
);
318 static int test_busyfork2(void)
320 struct pthreadpool_pipe
*p
;
325 ret
= pthreadpool_pipe_init(1, &p
);
327 fprintf(stderr
, "pthreadpool_pipe_init failed: %s\n",
332 ret
= pthreadpool_pipe_add_job(p
, 1, busyfork_job
, NULL
);
334 fprintf(stderr
, "pthreadpool_add_job failed: %s\n",
339 ret
= pthreadpool_pipe_finished_jobs(p
, &jobnum
, 1);
341 fprintf(stderr
, "pthreadpool_pipe_finished_jobs failed\n");
345 ret
= poll(NULL
, 0, 10);
347 perror("poll failed");
351 ret
= pthreadpool_pipe_add_job(p
, 1, busyfork_job
, NULL
);
353 fprintf(stderr
, "pthreadpool_add_job failed: %s\n",
359 * Do the fork right after the add_job. This tests a race
360 * where the atfork prepare handler gets all idle threads off
361 * the condvar. If we are faster doing the fork than the
362 * existing idle thread could get out of idle and take the
363 * job, after the fork we end up with no threads to take care
369 perror("fork failed");
377 pfd
= (struct pollfd
) {
378 .fd
= pthreadpool_pipe_signal_fd(p
),
379 .events
= POLLIN
|POLLERR
383 ret
= poll(&pfd
, 1, 5000);
384 } while ((ret
== -1) && (errno
== EINTR
));
387 fprintf(stderr
, "job unfinished after 5 seconds\n");
394 static void test_tevent_wait(void *private_data
)
396 int *timeout
= private_data
;
397 poll(NULL
, 0, *timeout
);
400 static int test_tevent_1(void)
402 struct tevent_context
*ev
;
403 struct pthreadpool_tevent
*pool
;
404 struct tevent_req
*req1
, *req2
;
406 int timeout100
= 100;
410 ev
= tevent_context_init(NULL
);
413 fprintf(stderr
, "tevent_context_init failed: %s\n",
417 ret
= pthreadpool_tevent_init(ev
, UINT_MAX
, &pool
);
419 fprintf(stderr
, "pthreadpool_tevent_init failed: %s\n",
424 req1
= pthreadpool_tevent_job_send(
425 ev
, ev
, pool
, test_tevent_wait
, &timeout10
);
427 fprintf(stderr
, "pthreadpool_tevent_job_send failed\n");
431 req2
= pthreadpool_tevent_job_send(
432 ev
, ev
, pool
, test_tevent_wait
, &timeout100
);
434 fprintf(stderr
, "pthreadpool_tevent_job_send failed\n");
438 ok
= tevent_req_poll(req2
, ev
);
441 fprintf(stderr
, "tevent_req_poll failed: %s\n",
446 ret
= pthreadpool_tevent_job_recv(req1
);
449 fprintf(stderr
, "tevent_req_poll failed: %s\n",
457 ret
= tevent_loop_wait(ev
);
459 fprintf(stderr
, "tevent_loop_wait failed\n");
472 ret
= test_tevent_1();
474 fprintf(stderr
, "test_event_1 failed: %s\n",
481 fprintf(stderr
, "test_init failed\n");
487 fprintf(stderr
, "test_fork failed\n");
491 ret
= test_jobs(10, 10000);
493 fprintf(stderr
, "test_jobs failed\n");
497 ret
= test_busydestroy();
499 fprintf(stderr
, "test_busydestroy failed\n");
503 ret
= test_busyfork();
505 fprintf(stderr
, "test_busyfork failed\n");
509 ret
= test_busyfork2();
511 fprintf(stderr
, "test_busyfork2 failed\n");