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)