Home | History | Annotate | Download | only in libcutils
      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 
    268