java_lang_ProcessManager.cpp revision adc854b798c1cfe3bfd4c27d68d5cee38ca617da
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * you may not use this file except in compliance with the License. 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * You may obtain a copy of the License at 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#define LOG_TAG "ProcessManager" 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <sys/types.h> 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <sys/wait.h> 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <unistd.h> 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <fcntl.h> 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <signal.h> 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <stdlib.h> 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <string.h> 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <errno.h> 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <dirent.h> 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "jni.h" 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "JNIHelp.h" 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "utils/Log.h" 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "AndroidSystemNatives.h" 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Environment variables. */ 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectextern char **environ; 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic jmethodID onExitMethod = NULL; 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic jfieldID descriptorField = NULL; 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#ifdef ANDROID 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// Keeps track of the system properties fd so we don't close it. 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic int androidSystemPropertiesFd = -1; 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#endif 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * These are constants shared with the higher level code in 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * ProcessManager.java. 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#define WAIT_STATUS_UNKNOWN (-1) // unknown child status 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#define WAIT_STATUS_NO_CHILDREN (-2) // no children to wait for 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#define WAIT_STATUS_STRANGE_ERRNO (-3) // observed an undocumented errno 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Closes a file descriptor. */ 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic int closeNow(int fd) { 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int result; 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project do { 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = close(fd); 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } while (result == -1 && errno == EINTR); 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Closes a file descriptor. */ 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void java_lang_ProcessManager_close(JNIEnv* env, 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jclass clazz, jobject javaDescriptor) { 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int fd = (*env)->GetIntField(env, javaDescriptor, descriptorField); 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (closeNow(fd) == -1) { 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jclass ioException = (*env)->FindClass(env, "java/io/IOException"); 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project (*env)->ThrowNew(env, ioException, strerror(errno)); 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Kills process with the given ID. 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void java_lang_ProcessManager_kill(JNIEnv* env, jclass clazz, jint pid) { 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int result = kill((pid_t) pid, SIGKILL); 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (result == -1) { 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniThrowIOException(env, errno); 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Loops indefinitely and calls ProcessManager.onExit() when children exit. 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void java_lang_ProcessManager_watchChildren(JNIEnv* env, jobject o) { 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (onExitMethod == NULL) { 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "staticInitialize() must run first."); 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (1) { 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int status; 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pid_t pid = wait(&status); 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (pid >= 0) { 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Extract real status. 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (WIFEXITED(status)) { 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = WEXITSTATUS(status); 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (WIFSIGNALED(status)) { 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = WTERMSIG(status); 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (WIFSTOPPED(status)) { 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = WSTOPSIG(status); 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = WAIT_STATUS_UNKNOWN; 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The pid should be -1 already, but force it here just in case 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * we somehow end up with some other negative value. 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pid = -1; 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project switch (errno) { 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case ECHILD: { 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Expected errno: There are no children to wait() 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for. The callback will sleep until it is 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * informed of another child coming to life. 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = WAIT_STATUS_NO_CHILDREN; 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case EINTR: { 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * An unblocked signal came in while waiting; just 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * retry the wait(). 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project default: { 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unexpected errno, so squawk! Note: Per the 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Linux docs, there are no errnos defined for 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * wait() other than the two that are handled 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * immediately above. 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project LOGE("Error %d calling wait(): %s", errno, 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project strerror(errno)); 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = WAIT_STATUS_STRANGE_ERRNO; 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project (*env)->CallVoidMethod(env, o, onExitMethod, pid, status); 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ((*env)->ExceptionOccurred(env)) { 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The callback threw, so break out of the loop and return, 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * letting the exception percolate up. 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Close all open fds > 2 (i.e. everything but stdin/out/err). */ 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void closeNonStandardFds(int skipFd) { 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project DIR* dir = opendir("/proc/self/fd"); 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (dir == NULL) { 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Print message to standard err. The parent process can read this 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // from Process.getErrorStream(). 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project perror("opendir"); 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project struct dirent* entry; 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int dirFd = dirfd(dir); 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while ((entry = readdir(dir)) != NULL) { 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int fd = atoi(entry->d_name); 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fd > 2 && fd != dirFd && fd != skipFd 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#ifdef ANDROID 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && fd != androidSystemPropertiesFd 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#endif 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ) { 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(fd); 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project closedir(dir); 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#define PIPE_COUNT (4) // number of pipes used to communicate with child proc 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Closes all pipes in the given array. */ 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void closePipes(int pipes[], int skipFd) { 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int i; 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (i = 0; i < PIPE_COUNT * 2; i++) { 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int fd = pipes[i]; 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fd == -1) { 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fd != skipFd) { 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(pipes[i]); 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Executes a command in a child process. */ 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic pid_t executeProcess(JNIEnv* env, char** commands, char** environment, 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project const char* workingDirectory, jobject inDescriptor, 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jobject outDescriptor, jobject errDescriptor) { 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int i, result, error; 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Create 4 pipes: stdin, stdout, stderr, and an exec() status pipe. 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int pipes[PIPE_COUNT * 2] = { -1, -1, -1, -1, -1, -1, -1, -1 }; 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (i = 0; i < PIPE_COUNT; i++) { 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (pipe(pipes + i * 2) == -1) { 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniThrowIOException(env, errno); 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project closePipes(pipes, -1); 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdinIn = pipes[0]; 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdinOut = pipes[1]; 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdoutIn = pipes[2]; 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdoutOut = pipes[3]; 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stderrIn = pipes[4]; 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stderrOut = pipes[5]; 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int statusIn = pipes[6]; 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int statusOut = pipes[7]; 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pid_t childPid = fork(); 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If fork() failed... 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (childPid == -1) { 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniThrowIOException(env, errno); 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project closePipes(pipes, -1); 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If this is the child process... 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (childPid == 0) { 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Replace stdin, out, and err with pipes. 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dup2(stdinIn, 0); 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dup2(stdoutOut, 1); 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dup2(stderrOut, 2); 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Close all but statusOut. This saves some work in the next step. 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project closePipes(pipes, statusOut); 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Make statusOut automatically close if execvp() succeeds. 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fcntl(statusOut, F_SETFD, FD_CLOEXEC); 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Close remaining open fds with the exception of statusOut. 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project closeNonStandardFds(statusOut); 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Switch to working directory. 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (workingDirectory != NULL) { 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (chdir(workingDirectory) == -1) { 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project goto execFailed; 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Set up environment. 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (environment != NULL) { 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project environ = environment; 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Execute process. By convention, the first argument in the arg array 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // should be the command itself. In fact, I get segfaults when this 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // isn't the case. 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project execvp(commands[0], commands); 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If we got here, execvp() failed or the working dir was invalid. 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project execFailed: 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project error = errno; 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project write(statusOut, &error, sizeof(int)); 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(statusOut); 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project exit(error); 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // This is the parent process. 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Close child's pipe ends. 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdinIn); 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdoutOut); 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stderrOut); 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(statusOut); 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Check status pipe for an error code. If execvp() succeeds, the other 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // end of the pipe should automatically close, in which case, we'll read 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // nothing. 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int count = read(statusIn, &result, sizeof(int)); 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(statusIn); 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (count > 0) { 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniThrowIOException(env, result); 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdoutIn); 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdinOut); 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stderrIn); 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Fill in file descriptor wrappers. 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniSetFileDescriptorOfFD(env, inDescriptor, stdoutIn); 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniSetFileDescriptorOfFD(env, outDescriptor, stdinOut); 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniSetFileDescriptorOfFD(env, errDescriptor, stderrIn); 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return childPid; 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Converts a Java String[] to a 0-terminated char**. */ 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic char** convertStrings(JNIEnv* env, jobjectArray javaArray) { 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (javaArray == NULL) { 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char** array = NULL; 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jsize length = (*env)->GetArrayLength(env, javaArray); 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project array = (char**) malloc(sizeof(char*) * (length + 1)); 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project array[length] = 0; 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jsize index; 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (index = 0; index < length; index++) { 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jstring javaEntry = (jstring) (*env)->GetObjectArrayElement( 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project env, javaArray, index); 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char* entry = (char*) (*env)->GetStringUTFChars( 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project env, javaEntry, NULL); 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project array[index] = entry; 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return array; 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Frees a char** which was converted from a Java String[]. */ 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void freeStrings(JNIEnv* env, jobjectArray javaArray, char** array) { 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (javaArray == NULL) { 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jsize length = (*env)->GetArrayLength(env, javaArray); 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jsize index; 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (index = 0; index < length; index++) { 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jstring javaEntry = (jstring) (*env)->GetObjectArrayElement( 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project env, javaArray, index); 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project (*env)->ReleaseStringUTFChars(env, javaEntry, array[index]); 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project free(array); 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Converts Java String[] to char** and delegates to executeProcess(). 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic pid_t java_lang_ProcessManager_exec( 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project JNIEnv* env, jclass clazz, jobjectArray javaCommands, 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jobjectArray javaEnvironment, jstring javaWorkingDirectory, 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jobject inDescriptor, jobject outDescriptor, jobject errDescriptor) { 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Copy commands into char*[]. 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char** commands = convertStrings(env, javaCommands); 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Extract working directory string. 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project const char* workingDirectory = NULL; 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (javaWorkingDirectory != NULL) { 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project workingDirectory = (const char*) (*env)->GetStringUTFChars( 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project env, javaWorkingDirectory, NULL); 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Convert environment array. 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char** environment = convertStrings(env, javaEnvironment); 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pid_t result = executeProcess( 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project env, commands, environment, workingDirectory, 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project inDescriptor, outDescriptor, errDescriptor); 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Temporarily clear exception so we can clean up. 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jthrowable exception = (*env)->ExceptionOccurred(env); 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project (*env)->ExceptionClear(env); 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project freeStrings(env, javaEnvironment, environment); 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Clean up working directory string. 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (javaWorkingDirectory != NULL) { 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project (*env)->ReleaseStringUTFChars( 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project env, javaWorkingDirectory, workingDirectory); 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project freeStrings(env, javaCommands, commands); 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Re-throw exception if present. 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (exception != NULL) { 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ((*env)->Throw(env, exception) < 0) { 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project LOGE("Error rethrowing exception!"); 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Looks up Java members. 396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void java_lang_ProcessManager_staticInitialize(JNIEnv* env, 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jclass clazz) { 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#ifdef ANDROID 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char* fdString = getenv("ANDROID_PROPERTY_WORKSPACE"); 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fdString) { 402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project androidSystemPropertiesFd = atoi(fdString); 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#endif 405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project onExitMethod = (*env)->GetMethodID(env, clazz, "onExit", "(II)V"); 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (onExitMethod == NULL) { 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jclass fileDescriptorClass 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project = (*env)->FindClass(env, "java/io/FileDescriptor"); 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fileDescriptorClass == NULL) { 414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project descriptorField = (*env)->GetFieldID(env, fileDescriptorClass, 417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "descriptor", "I"); 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (descriptorField == NULL) { 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic JNINativeMethod methods[] = { 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project { "kill", "(I)V", (void*) java_lang_ProcessManager_kill }, 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project { "watchChildren", "()V", (void*) java_lang_ProcessManager_watchChildren }, 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project { "exec", "([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;" 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;" 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Ljava/io/FileDescriptor;)I", (void*) java_lang_ProcessManager_exec }, 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project { "staticInitialize", "()V", 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project (void*) java_lang_ProcessManager_staticInitialize }, 431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project { "close", "(Ljava/io/FileDescriptor;)V", 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project (void*) java_lang_ProcessManager_close }, 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}; 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectint register_java_lang_ProcessManager(JNIEnv* env) { 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return jniRegisterNativeMethods( 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project env, "java/lang/ProcessManager", methods, NELEM(methods)); 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 439