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
39static 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 */
45static 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    //ALOGE("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
162int 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 */
216int 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 */
257static void replace_nl(char *str)
258{
259    for(; *str; str++) {
260        if (*str == '\n') {
261            *str = ' ';
262        }
263    }
264}
265
266
267
268