java_lang_ProcessManager.cpp revision 798f855f67b74d481346d9dc2293ba0eedd8daf9
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" 306c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes#include "Portability.h" 31e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes#include "ScopedLocalRef.h" 328545b837c61c3eaea2b8433b6791aa401f37e5f7Elliott Hughes#include "cutils/log.h" 33798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich#include "toStringArray.h" 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 35410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob/** Close all open fds > 2 (i.e. everything but stdin/out/err), != skipFd. */ 36a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughesstatic void closeNonStandardFds(int skipFd1, int skipFd2) { 3794367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes // TODO: rather than close all these non-open files, we could look in /proc/self/fd. 38e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes rlimit rlimit; 39410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob getrlimit(RLIMIT_NOFILE, &rlimit); 4094367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes const int max_fd = rlimit.rlim_max; 4194367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes for (int fd = 3; fd < max_fd; ++fd) { 42a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes if (fd != skipFd1 && fd != skipFd2) { 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(fd); 44410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob } 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#define PIPE_COUNT (4) // number of pipes used to communicate with child proc 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Closes all pipes in the given array. */ 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void closePipes(int pipes[], int skipFd) { 52a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes for (int i = 0; i < PIPE_COUNT * 2; i++) { 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int fd = pipes[i]; 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fd == -1) { 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fd != skipFd) { 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(pipes[i]); 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Executes a command in a child process. */ 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic pid_t executeProcess(JNIEnv* env, char** commands, char** environment, 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project const char* workingDirectory, jobject inDescriptor, 661805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes jobject outDescriptor, jobject errDescriptor, 671805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes jboolean redirectErrorStream) { 68a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes 69a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes // Keep track of the system properties fd so we don't close it. 70a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes int androidSystemPropertiesFd = -1; 71a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes char* fdString = getenv("ANDROID_PROPERTY_WORKSPACE"); 72a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes if (fdString) { 73a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes androidSystemPropertiesFd = atoi(fdString); 74a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes } 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Create 4 pipes: stdin, stdout, stderr, and an exec() status pipe. 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int pipes[PIPE_COUNT * 2] = { -1, -1, -1, -1, -1, -1, -1, -1 }; 78a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes for (int i = 0; i < PIPE_COUNT; i++) { 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (pipe(pipes + i * 2) == -1) { 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniThrowIOException(env, errno); 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project closePipes(pipes, -1); 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdinIn = pipes[0]; 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdinOut = pipes[1]; 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdoutIn = pipes[2]; 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdoutOut = pipes[3]; 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stderrIn = pipes[4]; 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stderrOut = pipes[5]; 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int statusIn = pipes[6]; 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int statusOut = pipes[7]; 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pid_t childPid = fork(); 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If fork() failed... 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (childPid == -1) { 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniThrowIOException(env, errno); 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project closePipes(pipes, -1); 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If this is the child process... 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (childPid == 0) { 105410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob /* 1066c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes * Note: We cannot malloc(3) or free(3) after this point! 1076c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes * A thread in the parent that no longer exists in the child may have held the heap lock 1086c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes * when we forked, so an attempt to malloc(3) or free(3) would result in deadlock. 109410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob */ 110410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Replace stdin, out, and err with pipes. 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dup2(stdinIn, 0); 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dup2(stdoutOut, 1); 1141805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes if (redirectErrorStream) { 1151805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes dup2(stdoutOut, 2); 1161805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes } else { 1171805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes dup2(stderrOut, 2); 1181805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes } 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Close all but statusOut. This saves some work in the next step. 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project closePipes(pipes, statusOut); 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Make statusOut automatically close if execvp() succeeds. 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fcntl(statusOut, F_SETFD, FD_CLOEXEC); 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 126a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes // Close remaining unwanted open fds. 127a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes closeNonStandardFds(statusOut, androidSystemPropertiesFd); 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Switch to working directory. 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (workingDirectory != NULL) { 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (chdir(workingDirectory) == -1) { 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project goto execFailed; 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Set up environment. 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (environment != NULL) { 138a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes extern char** environ; // Standard, but not in any header file. 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project environ = environment; 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Execute process. By convention, the first argument in the arg array 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // should be the command itself. In fact, I get segfaults when this 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // isn't the case. 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project execvp(commands[0], commands); 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If we got here, execvp() failed or the working dir was invalid. 1486c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott HughesexecFailed: 1496c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes int error = errno; 1506c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes write(statusOut, &error, sizeof(int)); 1516c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes close(statusOut); 1526c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes exit(error); 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // This is the parent process. 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Close child's pipe ends. 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdinIn); 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdoutOut); 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stderrOut); 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(statusOut); 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Check status pipe for an error code. If execvp() succeeds, the other 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // end of the pipe should automatically close, in which case, we'll read 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // nothing. 166a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes int result; 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int count = read(statusIn, &result, sizeof(int)); 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(statusIn); 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (count > 0) { 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniThrowIOException(env, result); 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdoutIn); 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdinOut); 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stderrIn); 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Fill in file descriptor wrappers. 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniSetFileDescriptorOfFD(env, inDescriptor, stdoutIn); 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniSetFileDescriptorOfFD(env, outDescriptor, stdinOut); 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniSetFileDescriptorOfFD(env, errDescriptor, stderrIn); 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return childPid; 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Converts Java String[] to char** and delegates to executeProcess(). 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 190a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughesstatic pid_t ProcessManager_exec(JNIEnv* env, jclass, jobjectArray javaCommands, 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jobjectArray javaEnvironment, jstring javaWorkingDirectory, 1921805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes jobject inDescriptor, jobject outDescriptor, jobject errDescriptor, 1931805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes jboolean redirectErrorStream) { 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Copy commands into char*[]. 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char** commands = convertStrings(env, javaCommands); 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Extract working directory string. 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project const char* workingDirectory = NULL; 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (javaWorkingDirectory != NULL) { 20194367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes workingDirectory = env->GetStringUTFChars(javaWorkingDirectory, NULL); 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Convert environment array. 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char** environment = convertStrings(env, javaEnvironment); 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 207a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes pid_t result = executeProcess(env, commands, environment, workingDirectory, 2081805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes inDescriptor, outDescriptor, errDescriptor, redirectErrorStream); 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Temporarily clear exception so we can clean up. 21194367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes jthrowable exception = env->ExceptionOccurred(); 21294367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes env->ExceptionClear(); 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project freeStrings(env, javaEnvironment, environment); 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Clean up working directory string. 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (javaWorkingDirectory != NULL) { 21894367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes env->ReleaseStringUTFChars(javaWorkingDirectory, workingDirectory); 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project freeStrings(env, javaCommands, commands); 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Re-throw exception if present. 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (exception != NULL) { 22594367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes if (env->Throw(exception) < 0) { 226679cf68b607e9b4a3beb8bcdee06868ae583386fSteve Block ALOGE("Error rethrowing exception!"); 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic JNINativeMethod methods[] = { 234e22935d3c7040c22b48d53bd18878844f381287cElliott 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"), 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}; 2367cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughesvoid register_java_lang_ProcessManager(JNIEnv* env) { 2377cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughes jniRegisterNativeMethods(env, "java/lang/ProcessManager", methods, NELEM(methods)); 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 239