123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- /*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #define LOG_TAG "Zygote"
- #include <cutils/sockets.h>
- #include <cutils/zygote.h>
- #include <cutils/log.h>
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <time.h>
- #include <stdint.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #define ZYGOTE_SOCKET "zygote"
- #define ZYGOTE_RETRY_COUNT 1000
- #define ZYGOTE_RETRY_MILLIS 500
- static void replace_nl(char *str);
- /*
- * If sendStdio is non-zero, the current process's stdio file descriptors
- * will be sent and inherited by the spawned process.
- */
- static int send_request(int fd, int sendStdio, int argc, const char **argv)
- {
- #ifndef HAVE_ANDROID_OS
- // not supported on simulator targets
- //ALOGE("zygote_* not supported on simulator targets");
- return -1;
- #else /* HAVE_ANDROID_OS */
- uint32_t pid;
- int i;
- struct iovec ivs[2];
- struct msghdr msg;
- char argc_buffer[12];
- const char *newline_string = "\n";
- struct cmsghdr *cmsg;
- char msgbuf[CMSG_SPACE(sizeof(int) * 3)];
- int *cmsg_payload;
- ssize_t ret;
- memset(&msg, 0, sizeof(msg));
- memset(&ivs, 0, sizeof(ivs));
- // First line is arg count
- snprintf(argc_buffer, sizeof(argc_buffer), "%d\n", argc);
- ivs[0].iov_base = argc_buffer;
- ivs[0].iov_len = strlen(argc_buffer);
- msg.msg_iov = ivs;
- msg.msg_iovlen = 1;
- if (sendStdio != 0) {
- // Pass the file descriptors with the first write
- msg.msg_control = msgbuf;
- msg.msg_controllen = sizeof msgbuf;
- cmsg = CMSG_FIRSTHDR(&msg);
- cmsg->cmsg_len = CMSG_LEN(3 * sizeof(int));
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg_payload = (int *)CMSG_DATA(cmsg);
- cmsg_payload[0] = STDIN_FILENO;
- cmsg_payload[1] = STDOUT_FILENO;
- cmsg_payload[2] = STDERR_FILENO;
- }
- do {
- ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
- } while (ret < 0 && errno == EINTR);
- if (ret < 0) {
- return -1;
- }
- // Only send the fd's once
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- // replace any newlines with spaces and send the args
- for (i = 0; i < argc; i++) {
- char *tofree = NULL;
- const char *toprint;
- toprint = argv[i];
- if (strchr(toprint, '\n') != NULL) {
- tofree = strdup(toprint);
- toprint = tofree;
- replace_nl(tofree);
- }
- ivs[0].iov_base = (char *)toprint;
- ivs[0].iov_len = strlen(toprint);
- ivs[1].iov_base = (char *)newline_string;
- ivs[1].iov_len = 1;
- msg.msg_iovlen = 2;
- do {
- ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
- } while (ret < 0 && errno == EINTR);
- if (tofree != NULL) {
- free(tofree);
- }
- if (ret < 0) {
- return -1;
- }
- }
- // Read the pid, as a 4-byte network-order integer
- ivs[0].iov_base = &pid;
- ivs[0].iov_len = sizeof(pid);
- msg.msg_iovlen = 1;
- do {
- do {
- ret = recvmsg(fd, &msg, MSG_NOSIGNAL | MSG_WAITALL);
- } while (ret < 0 && errno == EINTR);
- if (ret < 0) {
- return -1;
- }
- ivs[0].iov_len -= ret;
- ivs[0].iov_base += ret;
- } while (ivs[0].iov_len > 0);
- pid = ntohl(pid);
- return pid;
- #endif /* HAVE_ANDROID_OS */
- }
- int zygote_run_wait(int argc, const char **argv, void (*post_run_func)(int))
- {
- int fd;
- int pid;
- int err;
- const char *newargv[argc + 1];
- fd = socket_local_client(ZYGOTE_SOCKET,
- ANDROID_SOCKET_NAMESPACE_RESERVED, AF_LOCAL);
- if (fd < 0) {
- return -1;
- }
- // The command socket is passed to the peer as close-on-exec
- // and will close when the peer dies
- newargv[0] = "--peer-wait";
- memcpy(newargv + 1, argv, argc * sizeof(*argv));
- pid = send_request(fd, 1, argc + 1, newargv);
- if (pid > 0 && post_run_func != NULL) {
- post_run_func(pid);
- }
- // Wait for socket to close
- do {
- int dummy;
- err = read(fd, &dummy, sizeof(dummy));
- } while ((err < 0 && errno == EINTR) || err != 0);
- do {
- err = close(fd);
- } while (err < 0 && errno == EINTR);
- return 0;
- }
- /**
- * Spawns a new dalvik instance via the Zygote process. The non-zygote
- * arguments are passed to com.android.internal.os.RuntimeInit(). The
- * first non-option argument should be a class name in the system class path.
- *
- * The arg list may start with zygote params such as --set-uid.
- *
- * If sendStdio is non-zero, the current process's stdio file descriptors
- * will be sent and inherited by the spawned process.
- *
- * The pid of the child process is returned, or -1 if an error was
- * encountered.
- *
- * zygote_run_oneshot waits up to ZYGOTE_RETRY_COUNT *
- * ZYGOTE_RETRY_MILLIS for the zygote socket to be available.
- */
- int zygote_run_oneshot(int sendStdio, int argc, const char **argv)
- {
- int fd = -1;
- int err;
- int i;
- int retries;
- int pid;
- const char **newargv = argv;
- const int newargc = argc;
- for (retries = 0; (fd < 0) && (retries < ZYGOTE_RETRY_COUNT); retries++) {
- if (retries > 0) {
- struct timespec ts;
- memset(&ts, 0, sizeof(ts));
- ts.tv_nsec = ZYGOTE_RETRY_MILLIS * 1000 * 1000;
- do {
- err = nanosleep (&ts, &ts);
- } while (err < 0 && errno == EINTR);
- }
- fd = socket_local_client(ZYGOTE_SOCKET, AF_LOCAL,
- ANDROID_SOCKET_NAMESPACE_RESERVED);
- }
- if (fd < 0) {
- return -1;
- }
- pid = send_request(fd, 0, newargc, newargv);
- do {
- err = close(fd);
- } while (err < 0 && errno == EINTR);
- return pid;
- }
- /**
- * Replaces all occurrances of newline with space.
- */
- static void replace_nl(char *str)
- {
- for(; *str; str++) {
- if (*str == '\n') {
- *str = ' ';
- }
- }
- }
|