OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / system / core / libcutils / zygote.c
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define LOG_TAG "Zygote"
18
19 #include <cutils/sockets.h>
20 #include <cutils/zygote.h>
21 #include <cutils/log.h>
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <time.h>
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <arpa/inet.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33
34 #define ZYGOTE_SOCKET "zygote"
35
36 #define ZYGOTE_RETRY_COUNT 1000
37 #define ZYGOTE_RETRY_MILLIS 500
38
39 static void replace_nl(char *str);
40
41 /*
42  * If sendStdio is non-zero, the current process's stdio file descriptors
43  * will be sent and inherited by the spawned process.
44  */
45 static int send_request(int fd, int sendStdio, int argc, const char **argv)
46 {
47 #ifndef HAVE_ANDROID_OS
48     // not supported on simulator targets
49     //LOGE("zygote_* not supported on simulator targets");
50     return -1;
51 #else /* HAVE_ANDROID_OS */
52     uint32_t pid;
53     int i;
54     struct iovec ivs[2];
55     struct msghdr msg;
56     char argc_buffer[12];
57     const char *newline_string = "\n";
58     struct cmsghdr *cmsg;
59     char msgbuf[CMSG_SPACE(sizeof(int) * 3)];
60     int *cmsg_payload;
61     ssize_t ret;
62
63     memset(&msg, 0, sizeof(msg));
64     memset(&ivs, 0, sizeof(ivs));
65
66     // First line is arg count 
67     snprintf(argc_buffer, sizeof(argc_buffer), "%d\n", argc);
68
69     ivs[0].iov_base = argc_buffer;
70     ivs[0].iov_len = strlen(argc_buffer);
71
72     msg.msg_iov = ivs;
73     msg.msg_iovlen = 1;
74
75     if (sendStdio != 0) {
76         // Pass the file descriptors with the first write
77         msg.msg_control = msgbuf;
78         msg.msg_controllen = sizeof msgbuf;
79
80         cmsg = CMSG_FIRSTHDR(&msg);
81
82         cmsg->cmsg_len = CMSG_LEN(3 * sizeof(int));
83         cmsg->cmsg_level = SOL_SOCKET;
84         cmsg->cmsg_type = SCM_RIGHTS;
85
86         cmsg_payload = (int *)CMSG_DATA(cmsg);
87         cmsg_payload[0] = STDIN_FILENO;
88         cmsg_payload[1] = STDOUT_FILENO;
89         cmsg_payload[2] = STDERR_FILENO;
90     }
91
92     do {
93         ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
94     } while (ret < 0 && errno == EINTR);
95
96     if (ret < 0) {
97         return -1;
98     }
99
100     // Only send the fd's once
101     msg.msg_control = NULL;
102     msg.msg_controllen = 0;
103
104     // replace any newlines with spaces and send the args
105     for (i = 0; i < argc; i++) {
106         char *tofree = NULL;
107         const char *toprint;
108
109         toprint = argv[i];
110
111         if (strchr(toprint, '\n') != NULL) {
112             tofree = strdup(toprint);
113             toprint = tofree;
114             replace_nl(tofree);
115         }
116
117         ivs[0].iov_base = (char *)toprint;
118         ivs[0].iov_len = strlen(toprint);
119         ivs[1].iov_base = (char *)newline_string;
120         ivs[1].iov_len = 1;
121
122         msg.msg_iovlen = 2;
123
124         do {
125             ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
126         } while (ret < 0 && errno == EINTR);
127
128         if (tofree != NULL) {
129             free(tofree);
130         }
131
132         if (ret < 0) {
133             return -1;
134         }
135     }
136
137     // Read the pid, as a 4-byte network-order integer
138
139     ivs[0].iov_base = &pid;
140     ivs[0].iov_len = sizeof(pid);
141     msg.msg_iovlen = 1;
142
143     do {
144         do {
145             ret = recvmsg(fd, &msg, MSG_NOSIGNAL | MSG_WAITALL);
146         } while (ret < 0 && errno == EINTR);
147
148         if (ret < 0) {
149             return -1;
150         }
151
152         ivs[0].iov_len -= ret;
153         ivs[0].iov_base += ret;
154     } while (ivs[0].iov_len > 0);
155
156     pid = ntohl(pid);
157
158     return pid;
159 #endif /* HAVE_ANDROID_OS */
160 }
161
162 int zygote_run_wait(int argc, const char **argv, void (*post_run_func)(int))
163 {
164     int fd;
165     int pid;
166     int err;
167     const char *newargv[argc + 1];
168
169     fd = socket_local_client(ZYGOTE_SOCKET, 
170             ANDROID_SOCKET_NAMESPACE_RESERVED, AF_LOCAL);
171
172     if (fd < 0) {
173         return -1;
174     }
175
176     // The command socket is passed to the peer as close-on-exec
177     // and will close when the peer dies
178     newargv[0] = "--peer-wait";
179     memcpy(newargv + 1, argv, argc * sizeof(*argv)); 
180
181     pid = send_request(fd, 1, argc + 1, newargv);
182
183     if (pid > 0 && post_run_func != NULL) {
184         post_run_func(pid);
185     }
186
187     // Wait for socket to close
188     do {
189         int dummy;
190         err = read(fd, &dummy, sizeof(dummy));
191     } while ((err < 0 && errno == EINTR) || err != 0);
192
193     do {
194         err = close(fd);
195     } while (err < 0 && errno == EINTR);
196
197     return 0;
198 }
199
200 /**
201  * Spawns a new dalvik instance via the Zygote process. The non-zygote
202  * arguments are passed to com.android.internal.os.RuntimeInit(). The
203  * first non-option argument should be a class name in the system class path.
204  *
205  * The arg list  may start with zygote params such as --set-uid.
206  *
207  * If sendStdio is non-zero, the current process's stdio file descriptors
208  * will be sent and inherited by the spawned process.
209  *
210  * The pid of the child process is returned, or -1 if an error was 
211  * encountered.
212  *
213  * zygote_run_oneshot waits up to ZYGOTE_RETRY_COUNT * 
214  * ZYGOTE_RETRY_MILLIS for the zygote socket to be available.
215  */
216 int zygote_run_oneshot(int sendStdio, int argc, const char **argv) 
217 {
218     int fd = -1;
219     int err;
220     int i;
221     int retries;
222     int pid;
223     const char **newargv = argv;
224     const int newargc = argc;
225
226     for (retries = 0; (fd < 0) && (retries < ZYGOTE_RETRY_COUNT); retries++) {
227         if (retries > 0) { 
228             struct timespec ts;
229
230             memset(&ts, 0, sizeof(ts));
231             ts.tv_nsec = ZYGOTE_RETRY_MILLIS * 1000 * 1000;
232
233             do {
234                 err = nanosleep (&ts, &ts);
235             } while (err < 0 && errno == EINTR);
236         }
237         fd = socket_local_client(ZYGOTE_SOCKET, AF_LOCAL, 
238                 ANDROID_SOCKET_NAMESPACE_RESERVED);
239     }
240
241     if (fd < 0) {
242         return -1;
243     }
244
245     pid = send_request(fd, 0, newargc, newargv);
246
247     do {
248         err = close(fd);
249     } while (err < 0 && errno == EINTR);
250
251     return pid;
252 }
253
254 /**
255  * Replaces all occurrances of newline with space.
256  */
257 static void replace_nl(char *str)
258 {
259     for(; *str; str++) {
260         if (*str == '\n') {
261             *str = ' ';
262         }
263     }
264 }
265
266
267