src/windows/native/java/lang/ProcessImpl_md.c
Print this page
*** 61,210 ****
{
if (handle != INVALID_HANDLE_VALUE)
CloseHandle(handle);
}
! JNIEXPORT jlong JNICALL
! Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
! jstring cmd,
! jstring envBlock,
! jstring dir,
! jlongArray stdHandles,
! jboolean redirectErrorStream)
{
! HANDLE inRead = INVALID_HANDLE_VALUE;
! HANDLE inWrite = INVALID_HANDLE_VALUE;
! HANDLE outRead = INVALID_HANDLE_VALUE;
! HANDLE outWrite = INVALID_HANDLE_VALUE;
! HANDLE errRead = INVALID_HANDLE_VALUE;
! HANDLE errWrite = INVALID_HANDLE_VALUE;
! SECURITY_ATTRIBUTES sa;
! PROCESS_INFORMATION pi;
! STARTUPINFOW si;
! const jchar* pcmd = NULL;
! const jchar* pdir = NULL;
! const jchar* penvBlock = NULL;
! jlong *handles = NULL;
! jlong ret = 0;
! DWORD processFlag;
!
! assert(cmd != NULL);
! pcmd = (*env)->GetStringChars(env, cmd, NULL);
! if (pcmd == NULL) goto Catch;
!
! if (dir != 0) {
! pdir = (*env)->GetStringChars(env, dir, NULL);
! if (pdir == NULL) goto Catch;
! }
! if (envBlock != NULL) {
! penvBlock = ((*env)->GetStringChars(env, envBlock, NULL));
! if (penvBlock == NULL) goto Catch;
! }
! assert(stdHandles != NULL);
! handles = (*env)->GetLongArrayElements(env, stdHandles, NULL);
! if (handles == NULL) goto Catch;
!
! memset(&si, 0, sizeof(si));
! si.cb = sizeof(si);
! si.dwFlags = STARTF_USESTDHANDLES;
! sa.nLength = sizeof(sa);
! sa.lpSecurityDescriptor = 0;
! sa.bInheritHandle = TRUE;
!
! if (handles[0] != (jlong) -1) {
! si.hStdInput = (HANDLE) handles[0];
! handles[0] = (jlong) -1;
} else {
! if (! CreatePipe(&inRead, &inWrite, &sa, PIPE_SIZE)) {
win32Error(env, "CreatePipe");
! goto Catch;
}
- si.hStdInput = inRead;
- SetHandleInformation(inWrite, HANDLE_FLAG_INHERIT, 0);
- handles[0] = (jlong) inWrite;
}
! SetHandleInformation(si.hStdInput,
! HANDLE_FLAG_INHERIT,
! HANDLE_FLAG_INHERIT);
! if (handles[1] != (jlong) -1) {
! si.hStdOutput = (HANDLE) handles[1];
! handles[1] = (jlong) -1;
! } else {
! if (! CreatePipe(&outRead, &outWrite, &sa, PIPE_SIZE)) {
! win32Error(env, "CreatePipe");
! goto Catch;
}
- si.hStdOutput = outWrite;
- SetHandleInformation(outRead, HANDLE_FLAG_INHERIT, 0);
- handles[1] = (jlong) outRead;
}
! SetHandleInformation(si.hStdOutput,
HANDLE_FLAG_INHERIT,
! HANDLE_FLAG_INHERIT);
if (redirectErrorStream) {
si.hStdError = si.hStdOutput;
handles[2] = (jlong) -1;
! } else if (handles[2] != (jlong) -1) {
! si.hStdError = (HANDLE) handles[2];
! handles[2] = (jlong) -1;
} else {
! if (! CreatePipe(&errRead, &errWrite, &sa, PIPE_SIZE)) {
! win32Error(env, "CreatePipe");
! goto Catch;
! }
! si.hStdError = errWrite;
! SetHandleInformation(errRead, HANDLE_FLAG_INHERIT, 0);
! handles[2] = (jlong) errRead;
}
- SetHandleInformation(si.hStdError,
- HANDLE_FLAG_INHERIT,
- HANDLE_FLAG_INHERIT);
! processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT;
! ret = CreateProcessW(0, /* executable name */
(LPWSTR)pcmd, /* command line */
! 0, /* process security attribute */
! 0, /* thread security attribute */
TRUE, /* inherits system handles */
processFlag, /* selected based on exe type */
(LPVOID)penvBlock,/* environment block */
(LPCWSTR)pdir, /* change to the new current directory */
&si, /* (in) startup information */
! &pi); /* (out) process information */
! if (!ret) {
win32Error(env, "CreateProcess");
! goto Catch;
! }
!
! CloseHandle(pi.hThread);
ret = (jlong)pi.hProcess;
! Finally:
! /* Always clean up the child's side of the pipes */
! closeSafely(inRead);
! closeSafely(outWrite);
! closeSafely(errWrite);
! if (pcmd != NULL)
! (*env)->ReleaseStringChars(env, cmd, pcmd);
if (pdir != NULL)
(*env)->ReleaseStringChars(env, dir, pdir);
if (penvBlock != NULL)
(*env)->ReleaseStringChars(env, envBlock, penvBlock);
! if (handles != NULL)
! (*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0);
return ret;
-
- Catch:
- /* Clean up the parent's side of the pipes in case of failure only */
- closeSafely(inWrite);
- closeSafely(outRead);
- closeSafely(errRead);
- goto Finally;
}
JNIEXPORT jint JNICALL
Java_java_lang_ProcessImpl_getExitCodeProcess(JNIEnv *env, jclass ignored, jlong handle)
{
--- 61,303 ----
{
if (handle != INVALID_HANDLE_VALUE)
CloseHandle(handle);
}
! static BOOL hasInheritFlag(HANDLE handle)
{
! DWORD mask;
! if (GetHandleInformation(handle, &mask)) {
! return mask & HANDLE_FLAG_INHERIT;
! }
! return FALSE;
! }
! #define HANDLE_STORAGE_SIZE 6
! #define OFFSET_READ 0
! #define OFFSET_WRITE 1
! #define OPPOSITE_END(offset) (offset==OFFSET_READ ? OFFSET_WRITE : OFFSET_READ)
!
! typedef struct _STDHOLDER {
! HANDLE pipe[2];
! int offset;
! } STDHOLDER;
!
! static BOOL initHolder(
! JNIEnv *env,
! STDHOLDER *pHolder,
! jlong *pjhandles,
! HANDLE *phStd)
! {
! if (*pjhandles != (jlong) -1) {
! *phStd = (HANDLE) *pjhandles;
! *pjhandles = (jlong) -1;
} else {
! if (!CreatePipe(
! &pHolder->pipe[OFFSET_READ],
! &pHolder->pipe[OFFSET_WRITE],
! NULL, /* we would like to inherit
! default process access,
! instead of 'Everybody' access */
! PIPE_SIZE))
! {
win32Error(env, "CreatePipe");
! return FALSE;
! } else {
! /* [thisProcessEnd] has no the inherit flag.
! the [lpPipeAttributes] param had the NULL value. */
! HANDLE thisProcessEnd = pHolder->pipe[OPPOSITE_END(pHolder->offset)];
! *phStd = pHolder->pipe[pHolder->offset];
! *pjhandles = (jlong) thisProcessEnd;
}
}
! /* Pipe handle will be closed in the [releaseHolder] call,
! file handle will be closed in Java.
! The long-live handle need to restore the inherit flag,
! we do it later in the [prepareIOEHandleState] call. */
! SetHandleInformation(
! *phStd,
! HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
! return TRUE;
! }
! static void releaseHolder(BOOL complete, STDHOLDER *pHolder) {
! closeSafely(pHolder->pipe[pHolder->offset]);
! if (complete) {
! /* Error occur, close this process pipe end */
! closeSafely(pHolder->pipe[OPPOSITE_END(pHolder->offset)]);
! }
! }
!
! static void prepareIOEHandleState(
! HANDLE *stdIOE,
! BOOL *inherit)
! {
! int i;
! for (i = 0; i < HANDLE_STORAGE_SIZE; ++i) {
! HANDLE hstd = stdIOE[i];
! if (INVALID_HANDLE_VALUE != hstd && hasInheritFlag(hstd)) {
! /* FALSE by default */
! inherit[i] = TRUE;
! /* Java does not need implicit inheritance for IOE handles,
! so we drop inherit flag that probably was installed by
! previous CreateProcess call that launched current process.
! We will return the handle state back after CreateProcess call.
! By clearing inherit flag we prevent "greedy grandchild" birth.
! The explicit inheritance for child process IOE handles is
! supported in the [initHolder] call. */
! SetHandleInformation(hstd, HANDLE_FLAG_INHERIT, 0);
}
}
! }
!
! static void restoreIOEHandleState(
! const HANDLE *stdIOE,
! const BOOL *inherit)
! {
! /* The set of current process standard IOE handles and
! the set of child process IOE handles can intersect.
! To restore the inherit flag right, we use backward
! array iteration. */
! int i;
! for (i = HANDLE_STORAGE_SIZE - 1; i >= 0; --i)
! if (INVALID_HANDLE_VALUE != stdIOE[i]) {
! /* Restore inherit flag for any case.
! The handle can be changed by explicit inheritance.*/
! SetHandleInformation(stdIOE[i],
HANDLE_FLAG_INHERIT,
! inherit[i] ? HANDLE_FLAG_INHERIT : 0);
! }
! }
!
! /* Please, read about the MS inheritance problem
! http://support.microsoft.com/kb/315939
! and critical section/synchronized block solution. */
! static jlong processCreate(
! JNIEnv *env,
! const jchar *pcmd,
! const jchar *penvBlock,
! const jchar *pdir,
! jlong *handles,
! jboolean redirectErrorStream)
! {
! jlong ret = 0L;
! STARTUPINFOW si = {sizeof(si)};
!
! /* Handles for which the inheritance flag must be restored. */
! HANDLE stdIOE[HANDLE_STORAGE_SIZE] = {
! /* Current process standard IOE handles: JDK-7147084 */
! INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
! /* Child process IOE handles: JDK-6921885 */
! (HANDLE)handles[0], (HANDLE)handles[1], (HANDLE)handles[2]};
! BOOL inherit[HANDLE_STORAGE_SIZE] = {
! FALSE, FALSE, FALSE,
! FALSE, FALSE, FALSE};
!
! {
! /* Extraction of current process standard IOE handles */
! DWORD idsIOE[3] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE};
! int i;
! for (i = 0; i < 3; ++i)
! /* Should not be closed by CloseHandle! */
! stdIOE[i] = GetStdHandle(idsIOE[i]);
! }
+ prepareIOEHandleState(stdIOE, inherit);
+ {
+ /* Input */
+ STDHOLDER holderIn = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_READ};
+ if (initHolder(env, &holderIn, &handles[0], &si.hStdInput)) {
+
+ /* Output */
+ STDHOLDER holderOut = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_WRITE};
+ if (initHolder(env, &holderOut, &handles[1], &si.hStdOutput)) {
+
+ /* Error */
+ STDHOLDER holderErr = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_WRITE};
+ BOOL success;
if (redirectErrorStream) {
si.hStdError = si.hStdOutput;
handles[2] = (jlong) -1;
! success = TRUE;
} else {
! success = initHolder(env, &holderErr, &handles[2], &si.hStdError);
}
! if (success) {
! PROCESS_INFORMATION pi;
! DWORD processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT;
!
! si.dwFlags = STARTF_USESTDHANDLES;
! if (!CreateProcessW(
! NULL, /* executable name */
(LPWSTR)pcmd, /* command line */
! NULL, /* process security attribute */
! NULL, /* thread security attribute */
TRUE, /* inherits system handles */
processFlag, /* selected based on exe type */
(LPVOID)penvBlock,/* environment block */
(LPCWSTR)pdir, /* change to the new current directory */
&si, /* (in) startup information */
! &pi)) /* (out) process information */
! {
win32Error(env, "CreateProcess");
! } else {
! closeSafely(pi.hThread);
ret = (jlong)pi.hProcess;
+ }
+ }
+ releaseHolder(ret == 0, &holderErr);
+ releaseHolder(ret == 0, &holderOut);
+ }
+ releaseHolder(ret == 0, &holderIn);
+ }
+ }
+ restoreIOEHandleState(stdIOE, inherit);
! return ret;
! }
! JNIEXPORT jlong JNICALL
! Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
! jstring cmd,
! jstring envBlock,
! jstring dir,
! jlongArray stdHandles,
! jboolean redirectErrorStream)
! {
! jlong ret = 0;
! if (cmd != NULL
! && stdHandles != NULL)
! {
! const jchar *pcmd = (*env)->GetStringChars(env, cmd, NULL);
! if (pcmd != NULL) {
! const jchar *penvBlock = (envBlock != NULL)
! ? (*env)->GetStringChars(env, envBlock, NULL)
! : NULL;
! const jchar *pdir = (dir != NULL)
! ? (*env)->GetStringChars(env, dir, NULL)
! : NULL;
! jlong *handles = (*env)->GetLongArrayElements(env, stdHandles, NULL);
! if (handles != NULL) {
! ret = processCreate(
! env,
! pcmd,
! penvBlock,
! pdir,
! handles,
! redirectErrorStream);
! (*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0);
! }
if (pdir != NULL)
(*env)->ReleaseStringChars(env, dir, pdir);
if (penvBlock != NULL)
(*env)->ReleaseStringChars(env, envBlock, penvBlock);
! (*env)->ReleaseStringChars(env, cmd, pcmd);
! }
! }
return ret;
}
JNIEXPORT jint JNICALL
Java_java_lang_ProcessImpl_getExitCodeProcess(JNIEnv *env, jclass ignored, jlong handle)
{
*** 261,271 ****
JNIEXPORT jboolean JNICALL
Java_java_lang_ProcessImpl_isProcessAlive(JNIEnv *env, jclass ignored, jlong handle)
{
DWORD dwExitStatus;
! GetExitCodeProcess(handle, &dwExitStatus);
return dwExitStatus == STILL_ACTIVE;
}
JNIEXPORT jboolean JNICALL
Java_java_lang_ProcessImpl_closeHandle(JNIEnv *env, jclass ignored, jlong handle)
--- 354,364 ----
JNIEXPORT jboolean JNICALL
Java_java_lang_ProcessImpl_isProcessAlive(JNIEnv *env, jclass ignored, jlong handle)
{
DWORD dwExitStatus;
! GetExitCodeProcess((HANDLE) handle, &dwExitStatus);
return dwExitStatus == STILL_ACTIVE;
}
JNIEXPORT jboolean JNICALL
Java_java_lang_ProcessImpl_closeHandle(JNIEnv *env, jclass ignored, jlong handle)