java_lang_ProcessManager.cpp revision 7cd6760f7045d771faae8080a8c6150bf678f679
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 19410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob#include <sys/resource.h> 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <sys/types.h> 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <unistd.h> 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <fcntl.h> 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <stdlib.h> 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <string.h> 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <errno.h> 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "jni.h" 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "JNIHelp.h" 29a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes#include "JniConstants.h" 30e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes#include "ScopedLocalRef.h" 318545b837c61c3eaea2b8433b6791aa401f37e5f7Elliott Hughes#include "cutils/log.h" 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 33410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob/** Close all open fds > 2 (i.e. everything but stdin/out/err), != skipFd. */ 34a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughesstatic void closeNonStandardFds(int skipFd1, int skipFd2) { 3594367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes // TODO: rather than close all these non-open files, we could look in /proc/self/fd. 36e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes rlimit rlimit; 37410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob getrlimit(RLIMIT_NOFILE, &rlimit); 3894367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes const int max_fd = rlimit.rlim_max; 3994367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes for (int fd = 3; fd < max_fd; ++fd) { 40a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes if (fd != skipFd1 && fd != skipFd2) { 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(fd); 42410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob } 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#define PIPE_COUNT (4) // number of pipes used to communicate with child proc 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Closes all pipes in the given array. */ 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void closePipes(int pipes[], int skipFd) { 50a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes for (int i = 0; i < PIPE_COUNT * 2; i++) { 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int fd = pipes[i]; 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fd == -1) { 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fd != skipFd) { 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(pipes[i]); 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Executes a command in a child process. */ 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic pid_t executeProcess(JNIEnv* env, char** commands, char** environment, 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project const char* workingDirectory, jobject inDescriptor, 641805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes jobject outDescriptor, jobject errDescriptor, 651805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes jboolean redirectErrorStream) { 66a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes 67a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes // Keep track of the system properties fd so we don't close it. 68a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes int androidSystemPropertiesFd = -1; 69a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes char* fdString = getenv("ANDROID_PROPERTY_WORKSPACE"); 70a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes if (fdString) { 71a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes androidSystemPropertiesFd = atoi(fdString); 72a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes } 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Create 4 pipes: stdin, stdout, stderr, and an exec() status pipe. 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int pipes[PIPE_COUNT * 2] = { -1, -1, -1, -1, -1, -1, -1, -1 }; 76a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes for (int i = 0; i < PIPE_COUNT; i++) { 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (pipe(pipes + i * 2) == -1) { 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniThrowIOException(env, errno); 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project closePipes(pipes, -1); 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdinIn = pipes[0]; 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdinOut = pipes[1]; 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdoutIn = pipes[2]; 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdoutOut = pipes[3]; 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stderrIn = pipes[4]; 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stderrOut = pipes[5]; 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int statusIn = pipes[6]; 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int statusOut = pipes[7]; 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pid_t childPid = fork(); 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If fork() failed... 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (childPid == -1) { 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniThrowIOException(env, errno); 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project closePipes(pipes, -1); 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If this is the child process... 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (childPid == 0) { 103410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob /* 104410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob * Note: We cannot malloc() or free() after this point! 105410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob * A no-longer-running thread may be holding on to the heap lock, and 106410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob * an attempt to malloc() or free() would result in deadlock. 107410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob */ 108410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Replace stdin, out, and err with pipes. 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dup2(stdinIn, 0); 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dup2(stdoutOut, 1); 1121805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes if (redirectErrorStream) { 1131805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes dup2(stdoutOut, 2); 1141805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes } else { 1151805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes dup2(stderrOut, 2); 1161805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes } 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Close all but statusOut. This saves some work in the next step. 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project closePipes(pipes, statusOut); 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Make statusOut automatically close if execvp() succeeds. 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fcntl(statusOut, F_SETFD, FD_CLOEXEC); 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 124a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes // Close remaining unwanted open fds. 125a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes closeNonStandardFds(statusOut, androidSystemPropertiesFd); 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Switch to working directory. 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (workingDirectory != NULL) { 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (chdir(workingDirectory) == -1) { 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project goto execFailed; 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Set up environment. 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (environment != NULL) { 136a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes extern char** environ; // Standard, but not in any header file. 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project environ = environment; 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Execute process. By convention, the first argument in the arg array 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // should be the command itself. In fact, I get segfaults when this 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // isn't the case. 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project execvp(commands[0], commands); 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If we got here, execvp() failed or the working dir was invalid. 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project execFailed: 147a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes int error = errno; 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project write(statusOut, &error, sizeof(int)); 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(statusOut); 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project exit(error); 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // This is the parent process. 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Close child's pipe ends. 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdinIn); 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdoutOut); 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stderrOut); 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(statusOut); 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Check status pipe for an error code. If execvp() succeeds, the other 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // end of the pipe should automatically close, in which case, we'll read 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // nothing. 164a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes int result; 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int count = read(statusIn, &result, sizeof(int)); 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(statusIn); 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (count > 0) { 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniThrowIOException(env, result); 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdoutIn); 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdinOut); 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stderrIn); 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Fill in file descriptor wrappers. 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniSetFileDescriptorOfFD(env, inDescriptor, stdoutIn); 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniSetFileDescriptorOfFD(env, outDescriptor, stdinOut); 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniSetFileDescriptorOfFD(env, errDescriptor, stderrIn); 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return childPid; 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Converts a Java String[] to a 0-terminated char**. */ 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic char** convertStrings(JNIEnv* env, jobjectArray javaArray) { 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (javaArray == NULL) { 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 19194367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes jsize length = env->GetArrayLength(javaArray); 192583ce47780cae3a014ca46534e08f5c2adc8fa88Elliott Hughes char** array = new char*[length + 1]; 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project array[length] = 0; 194e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes for (jsize i = 0; i < length; ++i) { 195e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes ScopedLocalRef<jstring> javaEntry(env, reinterpret_cast<jstring>(env->GetObjectArrayElement(javaArray, i))); 196583ce47780cae3a014ca46534e08f5c2adc8fa88Elliott Hughes // We need to pass these strings to const-unfriendly code. 197e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes char* entry = const_cast<char*>(env->GetStringUTFChars(javaEntry.get(), NULL)); 198e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes array[i] = entry; 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return array; 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Frees a char** which was converted from a Java String[]. */ 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void freeStrings(JNIEnv* env, jobjectArray javaArray, char** array) { 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (javaArray == NULL) { 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 21094367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes jsize length = env->GetArrayLength(javaArray); 211e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes for (jsize i = 0; i < length; ++i) { 212e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes ScopedLocalRef<jstring> javaEntry(env, reinterpret_cast<jstring>(env->GetObjectArrayElement(javaArray, i))); 213e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes env->ReleaseStringUTFChars(javaEntry.get(), array[i]); 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 216583ce47780cae3a014ca46534e08f5c2adc8fa88Elliott Hughes delete[] array; 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Converts Java String[] to char** and delegates to executeProcess(). 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 222a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughesstatic pid_t ProcessManager_exec(JNIEnv* env, jclass, jobjectArray javaCommands, 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jobjectArray javaEnvironment, jstring javaWorkingDirectory, 2241805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes jobject inDescriptor, jobject outDescriptor, jobject errDescriptor, 2251805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes jboolean redirectErrorStream) { 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Copy commands into char*[]. 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char** commands = convertStrings(env, javaCommands); 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Extract working directory string. 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project const char* workingDirectory = NULL; 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (javaWorkingDirectory != NULL) { 23394367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes workingDirectory = env->GetStringUTFChars(javaWorkingDirectory, NULL); 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Convert environment array. 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char** environment = convertStrings(env, javaEnvironment); 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 239a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes pid_t result = executeProcess(env, commands, environment, workingDirectory, 2401805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes inDescriptor, outDescriptor, errDescriptor, redirectErrorStream); 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Temporarily clear exception so we can clean up. 24394367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes jthrowable exception = env->ExceptionOccurred(); 24494367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes env->ExceptionClear(); 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project freeStrings(env, javaEnvironment, environment); 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Clean up working directory string. 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (javaWorkingDirectory != NULL) { 25094367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes env->ReleaseStringUTFChars(javaWorkingDirectory, workingDirectory); 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project freeStrings(env, javaCommands, commands); 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Re-throw exception if present. 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (exception != NULL) { 25794367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes if (env->Throw(exception) < 0) { 258679cf68b607e9b4a3beb8bcdee06868ae583386fSteve Block ALOGE("Error rethrowing exception!"); 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic JNINativeMethod methods[] = { 266e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ProcessManager, exec, "([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Z)I"), 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}; 2687cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughesvoid register_java_lang_ProcessManager(JNIEnv* env) { 2697cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughes jniRegisterNativeMethods(env, "java/lang/ProcessManager", methods, NELEM(methods)); 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 271