blob: 37236e8a63963578d9cc2bce62fcc519bc87e4fc [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
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
Steve Block01dda202012-01-06 14:13:42 +000049 //ALOGE("zygote_* not supported on simulator targets");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050 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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800162/**
163 * Spawns a new dalvik instance via the Zygote process. The non-zygote
164 * arguments are passed to com.android.internal.os.RuntimeInit(). The
165 * first non-option argument should be a class name in the system class path.
166 *
167 * The arg list may start with zygote params such as --set-uid.
168 *
169 * If sendStdio is non-zero, the current process's stdio file descriptors
170 * will be sent and inherited by the spawned process.
171 *
172 * The pid of the child process is returned, or -1 if an error was
173 * encountered.
174 *
175 * zygote_run_oneshot waits up to ZYGOTE_RETRY_COUNT *
176 * ZYGOTE_RETRY_MILLIS for the zygote socket to be available.
177 */
178int zygote_run_oneshot(int sendStdio, int argc, const char **argv)
179{
180 int fd = -1;
181 int err;
182 int i;
183 int retries;
184 int pid;
185 const char **newargv = argv;
186 const int newargc = argc;
187
188 for (retries = 0; (fd < 0) && (retries < ZYGOTE_RETRY_COUNT); retries++) {
189 if (retries > 0) {
190 struct timespec ts;
191
192 memset(&ts, 0, sizeof(ts));
193 ts.tv_nsec = ZYGOTE_RETRY_MILLIS * 1000 * 1000;
194
195 do {
196 err = nanosleep (&ts, &ts);
197 } while (err < 0 && errno == EINTR);
198 }
199 fd = socket_local_client(ZYGOTE_SOCKET, AF_LOCAL,
200 ANDROID_SOCKET_NAMESPACE_RESERVED);
201 }
202
203 if (fd < 0) {
204 return -1;
205 }
206
207 pid = send_request(fd, 0, newargc, newargv);
208
209 do {
210 err = close(fd);
211 } while (err < 0 && errno == EINTR);
212
213 return pid;
214}
215
216/**
217 * Replaces all occurrances of newline with space.
218 */
219static void replace_nl(char *str)
220{
221 for(; *str; str++) {
222 if (*str == '\n') {
223 *str = ' ';
224 }
225 }
226}
227
228
229