Пример #1
0
  /**
   * Reads one start command from the command socket. If successful, a child is forked and a {@link
   * ZygoteInit.MethodAndArgsCaller} exception is thrown in that child while in the parent process,
   * the method returns normally. On failure, the child is not spawned and messages are printed to
   * the log and stderr. Returns a boolean status value indicating whether an end-of-file on the
   * command socket has been encountered.
   *
   * @return false if command socket should continue to be read from, or true if an end-of-file has
   *     been encountered.
   * @throws ZygoteInit.MethodAndArgsCaller trampoline to invoke main() method in child process
   */
  boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;

    try {
      args = readArgumentList();
      descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
      Log.w(TAG, "IOException on command socket " + ex.getMessage());
      closeSocket();
      return true;
    }

    if (args == null) {
      // EOF reached.
      closeSocket();
      return true;
    }

    /** the stderr of the most recent request, if avail */
    PrintStream newStderr = null;

    if (descriptors != null && descriptors.length >= 3) {
      newStderr = new PrintStream(new FileOutputStream(descriptors[2]));
    }

    int pid = -1;
    FileDescriptor childPipeFd = null;
    FileDescriptor serverPipeFd = null;

    try {
      parsedArgs = new Arguments(args);

      applyUidSecurityPolicy(parsedArgs, peer);
      applyRlimitSecurityPolicy(parsedArgs, peer);
      applyCapabilitiesSecurityPolicy(parsedArgs, peer);
      applyInvokeWithSecurityPolicy(parsedArgs, peer);

      applyDebuggerSystemProperty(parsedArgs);
      applyInvokeWithSystemProperty(parsedArgs);

      int[][] rlimits = null;

      if (parsedArgs.rlimits != null) {
        rlimits = parsedArgs.rlimits.toArray(intArray2d);
      }

      if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) {
        FileDescriptor[] pipeFds = Libcore.os.pipe();
        childPipeFd = pipeFds[1];
        serverPipeFd = pipeFds[0];
        ZygoteInit.setCloseOnExec(serverPipeFd, true);
      }

      pid =
          Zygote.forkAndSpecialize(
              parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits);
    } catch (IOException ex) {
      logAndPrintError(newStderr, "Exception creating pipe", ex);
    } catch (ErrnoException ex) {
      logAndPrintError(newStderr, "Exception creating pipe", ex);
    } catch (IllegalArgumentException ex) {
      logAndPrintError(newStderr, "Invalid zygote arguments", ex);
    } catch (ZygoteSecurityException ex) {
      logAndPrintError(newStderr, "Zygote security policy prevents request: ", ex);
    }

    try {
      if (pid == 0) {
        // in child
        IoUtils.closeQuietly(serverPipeFd);
        serverPipeFd = null;
        handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);

        // should never get here, the child is expected to either
        // throw ZygoteInit.MethodAndArgsCaller or exec().
        return true;
      } else {
        // in parent...pid of < 0 means failure
        IoUtils.closeQuietly(childPipeFd);
        childPipeFd = null;
        return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
      }
    } finally {
      IoUtils.closeQuietly(childPipeFd);
      IoUtils.closeQuietly(serverPipeFd);
    }
  }