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