Tizen 2.1 base
[platform/upstream/gcd.git] / dispatch-1.0 / testing / dispatch_proc.c
1 /*
2  * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
3  *
4  * @APPLE_APACHE_LICENSE_HEADER_START@
5  * 
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  * 
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  * 
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  * 
18  * @APPLE_APACHE_LICENSE_HEADER_END@
19  */
20
21 #include "config/config.h"
22
23 #include <dispatch/dispatch.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <assert.h>
28 #include <spawn.h>
29 #include <signal.h>
30 #include <libkern/OSAtomic.h>
31
32 #include "dispatch_test.h"
33
34 #define PID_CNT 5
35
36 static long event_cnt;
37
38 int
39 main(void)
40 {
41         dispatch_source_t proc;
42         int res;
43         pid_t pid;
44
45         test_start("Dispatch Proc");
46         
47         // Creates a process and register multiple observers.  Send a signal,
48         // exit the process, etc., and verify all observers were notified.
49         
50         //
51         // Simple child process that sleeps 2 seconds.
52         //
53         
54         posix_spawnattr_t attr;
55         res = posix_spawnattr_init(&attr);
56         assert(res == 0);
57         res = posix_spawnattr_setflags(&attr, POSIX_SPAWN_START_SUSPENDED);
58         assert(res == 0);
59
60         char* args[] = {
61                 "/bin/sleep", "2", NULL
62         };
63         
64         res = posix_spawnp(&pid, args[0], NULL, &attr, args, NULL);
65         if (res < 0) {
66                 perror(args[0]);
67                 exit(127);
68         }
69
70         res = posix_spawnattr_destroy(&attr);
71         assert(res == 0);
72
73         dispatch_queue_t completion = dispatch_queue_create("completion", NULL);
74         
75         assert(pid > 0);
76
77         //
78         // Suspend the "completion" queue when each observer is created.
79         // Each observer resumes the queue when the child process exits.
80         // If the queue is resumed too few times (indicating that not all
81         // observers received the exit event) then the test case will not exit
82         // within the alloted time and result in failure.
83         //
84         
85         int i;
86         for (i = 0; i < PID_CNT; ++i) {
87                 dispatch_suspend(completion);
88                 proc = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, pid, DISPATCH_PROC_EXIT, dispatch_get_main_queue());
89                 test_ptr_notnull("DISPATCH_SOURCE_TYPE_PROC", proc);
90
91                 dispatch_source_set_event_handler(proc, ^{
92                         long flags = dispatch_source_get_data(proc);
93                         test_long("DISPATCH_PROC_EXIT", flags, DISPATCH_PROC_EXIT);
94                         event_cnt++;
95                         dispatch_release(proc);
96                         dispatch_resume(completion);
97                 });
98
99                 dispatch_resume(proc);
100         }
101
102
103         //
104         // The completion block will be pending on the completion queue until it
105         // has been fully resumed, at which point the test will exit successfully.
106         //
107
108         dispatch_async(completion, ^{
109                 int status;
110                 int res2 = waitpid(pid, &status, 0);
111                 assert(res2 != -1);
112                 test_long("Sub-process exited", WEXITSTATUS(status) | WTERMSIG(status), 0);
113                 test_long("Event count", event_cnt, PID_CNT);
114                 test_stop();
115         });
116
117         kill(pid, SIGCONT);
118
119         dispatch_main();
120
121         return 0;
122 }