Index: vm/vmcore/src/kernel_classes/native/Runtime_win.cpp =================================================================== --- vm/vmcore/src/kernel_classes/native/Runtime_win.cpp (revision 449690) +++ vm/vmcore/src/kernel_classes/native/Runtime_win.cpp (working copy) @@ -36,9 +36,6 @@ { jlong *lp = (jlong*)env->GetLongArrayElements(la, 0); lp[0] = 0; - lp[1] = 0; - lp[2] = 0; - lp[3] = 0; env->ReleaseLongArrayElements(la, lp, 0); INFO(lpszMess); @@ -93,8 +90,8 @@ { TRACE("Creating child process ..."); - HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRd, hChildStdoutWr, - hChildStderrorRd, hChildStderrorWr; + HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup, hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup, + hChildStderrorRd, hChildStderrorWr, hChildStderrorRdDup; PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo; SECURITY_ATTRIBUTES saAttr; @@ -106,8 +103,9 @@ } // Get the the command to call and its arguments: - int l = 1024; - char *strCmnd = (char*)malloc(1024); + int btl = 1024; + int l = btl; + char *strCmnd = (char*)malloc(btl); *strCmnd = '\0'; jsize len = env->GetArrayLength(cmdarray); int cur_pos = 0; @@ -116,15 +114,14 @@ jstring jo = (jstring)env->GetObjectArrayElement(cmdarray, (jsize) i); const char *strChain = env->GetStringUTFChars(jo, 0); bool need_esc = (*strChain != '\"' && strchr(strChain, ' ') != NULL); - cur_pos += strlen(strChain) + 1 + (need_esc ? 0 : 2); + cur_pos += strlen(strChain) + (i == 0 ? 0 : 1) + (need_esc ? 0 : 2); while (l <= cur_pos) { - char *strtmp = (char*)malloc(l + 1024); + char *strtmp = (char*)malloc(l + btl); memcpy(strtmp, strCmnd, l); - l += 1024; + l += btl; free((void *)strCmnd); strCmnd = strtmp; } - if ( i != 0 ) { strcat(strCmnd, " "); } @@ -140,8 +137,8 @@ char *strEnvp = NULL; // Get the array, each element of which has environment variable settings: if (envp != NULL) { - int l = 1024; - strEnvp = (char*)malloc(1024); + int l = btl; + strEnvp = (char*)malloc(btl); *strEnvp = '\0'; len = env->GetArrayLength(envp); cur_pos = 0; @@ -150,9 +147,9 @@ const char* strChain = env->GetStringUTFChars(jo, 0); size_t tmp = strlen(strChain) + 1; while ((unsigned)l <= (cur_pos + tmp)) { - char *strtmp = (char*)malloc(l + 1024); + char *strtmp = (char*)malloc(l + btl); memcpy(strtmp, strEnvp, l); - l += 1024; + l += btl; free(strEnvp); strEnvp = strtmp; } @@ -167,33 +164,72 @@ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; + + // Preparation of the child process's STDOUT: + + // 1. Create a pipe for the child process's STDOUT. + if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) { + Error("Stdout pipe creation failed\n", env, la); + return; + } + + // 2. Create noninheritable read handle and close the inheritable read handle. + if( !DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup, 0, FALSE, DUPLICATE_SAME_ACCESS) ) { + CloseHandle(hChildStdoutRd); + CloseHandle(hChildStdoutWr); + Error("DuplicateHandle failed", env, la); + return; + } + CloseHandle(hChildStdoutRd); + + // Preparation of the child process's STDERROR: + + // 1. Create anonymous pipe to be STDERROR for child process. + if (! CreatePipe(&hChildStderrorRd, &hChildStderrorWr, &saAttr, 0)) { + CloseHandle(hChildStdoutRdDup); + CloseHandle(hChildStdoutWr); + Error("Stderror pipe creation failed\n", env, la); + return; + } + + // 2. Create a noninheritable duplicate of the read handle, and close the inheritable read handle. + if( !DuplicateHandle(GetCurrentProcess(), hChildStderrorRd, GetCurrentProcess(), &hChildStderrorRdDup, 0, FALSE, DUPLICATE_SAME_ACCESS) ) { + CloseHandle(hChildStdoutRdDup); + CloseHandle(hChildStdoutWr); + CloseHandle(hChildStderrorRd); + CloseHandle(hChildStderrorWr); + Error("DuplicateHandle failed", env, la); + return; + } + CloseHandle(hChildStderrorRd); + + // Preparation of the child process's STDIN: + + // 1. Create anonymous pipe to be STDIN for child process. + if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) { + CloseHandle(hChildStdoutRdDup); + CloseHandle(hChildStdoutWr); + CloseHandle(hChildStderrorRdDup); + CloseHandle(hChildStderrorWr); + Error("Stdin pipe creation failed\n", env, la); + return; + } + + // 2. Create a noninheritable duplicate of the write handle, and close the inheritable write handle. + if ( !DuplicateHandle(GetCurrentProcess(), hChildStdinWr, GetCurrentProcess(), &hChildStdinWrDup, 0, FALSE, DUPLICATE_SAME_ACCESS)) { + CloseHandle(hChildStdoutRdDup); + CloseHandle(hChildStdoutWr); + CloseHandle(hChildStderrorRdDup); + CloseHandle(hChildStderrorWr); + CloseHandle(hChildStdinRd); + CloseHandle(hChildStdinWr); + Error("DuplicateHandle failed", env, la); + return; + } + CloseHandle(hChildStdinWr); + + // Now create the child process: - // Create a pipe for the child process's STDOUT. - if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) { - Error("Stdout pipe creation failed\n", env, la); - return; - } - - // Create anonymous pipe to be STDERROR for child process. - if (! CreatePipe(&hChildStderrorRd, &hChildStderrorWr, &saAttr, 0)) { - CloseHandle(hChildStdoutRd); - CloseHandle(hChildStdoutWr); - Error("Stderror pipe creation failed\n", env, la); - return; - } - - // Create anonymous pipe to be STDIN for child process. - if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) { - CloseHandle(hChildStdoutRd); - CloseHandle(hChildStdoutWr); - CloseHandle(hChildStderrorRd); - CloseHandle(hChildStderrorWr); - Error("Stdin pipe creation failed\n", env, la); - return; - } - - // Now create the child process: - ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.hStdError = hChildStderrorWr; @@ -233,15 +269,15 @@ if (created) { CloseHandle(piProcInfo.hThread); jlong *lp = (jlong*)env->GetLongArrayElements(la, 0); - lp[0] = (jlong) piProcInfo.hProcess; - lp[1] = (jlong) hChildStdinWr; - lp[2] = (jlong) hChildStdoutRd; - lp[3] = (jlong) hChildStderrorRd; + lp[0] = (jlong) piProcInfo.hProcess; + lp[1] = (jlong) hChildStdinWrDup; + lp[2] = (jlong) hChildStdoutRdDup; + lp[3] = (jlong) hChildStderrorRdDup; env->ReleaseLongArrayElements(la, lp, 0); } else { - CloseHandle(hChildStdoutRd); - CloseHandle(hChildStderrorRd); - CloseHandle(hChildStdinWr); + CloseHandle(hChildStdoutRdDup); + CloseHandle(hChildStderrorRdDup); + CloseHandle(hChildStdinWrDup); } } @@ -282,7 +318,7 @@ TerminateProcess( (HANDLE) handle /* handle to the process */, - 0 /* exit code for the process */ ); + ERROR_PROCESS_ABORTED /* exit code for the process */ ); } void JNICALL Java_java_lang_Runtime_00024SubProcess_close0 (JNIEnv *env, jobject obj, jint handle) { @@ -365,7 +401,7 @@ JNIEnv *env, jobject obj, jlong inputHandle) { DWORD res = CloseHandle((HANDLE)(POINTER_SIZE_INT)inputHandle); - if (res == 0) { + if (res == 0 && GetLastError() != ERROR_INVALID_HANDLE) { ThrowError(env); } } @@ -423,5 +459,5 @@ void JNICALL Java_java_lang_Runtime_00024SubProcess_00024SubOutputStream_close0 (JNIEnv *env, jobject obj, jlong outputHandle) { DWORD res = CloseHandle((HANDLE)(POINTER_SIZE_INT)outputHandle /* handle to pipe */ ); - if (res == 0) ThrowError(env); + if (res == 0 && GetLastError() != ERROR_INVALID_HANDLE) ThrowError(env); } Index: vm/vmcore/src/kernel_classes/native/Runtime_lnx.cpp =================================================================== --- vm/vmcore/src/kernel_classes/native/Runtime_lnx.cpp (revision 449690) +++ vm/vmcore/src/kernel_classes/native/Runtime_lnx.cpp (working copy) @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -54,9 +55,6 @@ jboolean jb = true; jlong *lp = (jlong*)env->GetLongArrayElements(la, &jb); lp[0] = 0; - lp[1] = -1ll; - lp[2] = -1ll; - lp[3] = -1ll; env->ReleaseLongArrayElements(la, lp, 0); if (lpszMess != NULL) { INFO(lpszMess); @@ -299,36 +297,53 @@ } jint JNICALL Java_java_lang_Runtime_00024SubProcess_00024SubInputStream_available0 (JNIEnv *env, jobject obj, jlong inputHandle) { - struct pollfd r[1]; int res; + if (ioctl((int) inputHandle, FIONREAD, &res) == -1) { + if (errno == EINVAL) { + struct pollfd r[1]; - r[0].fd = (int) inputHandle; - r[0].events = POLLRDNORM; - r[0].revents = 0; + r[0].fd = (int) inputHandle; + r[0].events = POLLRDNORM; + r[0].revents = 0; - do { - res = poll(r, 1, 0); - } while (res == -1 && errno == EINTR); + do { + res = poll(r, 1, 0); + } while (res == -1 && errno == EINTR); - if (res == 1) { - if(r[0].revents & r[0].events) { - return 1; // Can we define the number certainly? Idea: can buffer be attached to pipe for preliminary reading or else one? + if (res == 1) { + if(r[0].revents & r[0].events) { + return 1; // So, in that case we can define one byte is available at least + } else if(r[0].revents & (POLLERR | POLLNVAL)) { + char mess[100]; + mess[0] = '\0'; + sprintf(mess, "%s", (r[0].revents & POLLERR ? "Some error condition has raised." : "Invalid request: handle closed.")); + jclass jc = env->FindClass((const char *)"java/io/IOException"); + env->ThrowNew(jc, (const char *) mess); + } + return 0; + } else if (res < 0) { + char mess[100]; + mess[0] = '\0'; + sprintf(mess, "It's impossible to identify if there are available bytes in the input stream! ERRNO=%d. %s", errno, strerror(errno)); + jclass jc = env->FindClass((const char *)"java/io/IOException"); + env->ThrowNew(jc, (const char *) mess); + } + return 0; + } else { + char mess[100]; + mess[0] = '\0'; + sprintf(mess, "%s", "Some error condition has raised."); + jclass jc = env->FindClass((const char *)"java/io/IOException"); + env->ThrowNew(jc, (const char *) mess); } - return 0; - } else if (res < 0) { - char mess[100]; - mess[0] = '\0'; - sprintf(mess, "It's impossible to identify if there are available bytes in the input stream! ERRNO=%d. %s", errno, strerror(errno)); - jclass jc = env->FindClass((const char *)"java/io/IOException"); - env->ThrowNew(jc, (const char *) mess); } - return 0; + return res; } void JNICALL Java_java_lang_Runtime_00024SubProcess_00024SubInputStream_close0 (JNIEnv *env, jobject obj, jlong inputHandle) { int res = close((int) inputHandle); - if (res == -1) { + if (res == -1 && errno != EBADF) { ThrowError(env); } } @@ -382,7 +397,7 @@ void JNICALL Java_java_lang_Runtime_00024SubProcess_00024SubOutputStream_close0 (JNIEnv *env, jobject obj, jlong outputHandle) { int res = close((int) outputHandle); - if (res == -1) { + if (res == -1 && errno != EBADF) { ThrowError(env); } } Index: vm/vmcore/src/kernel_classes/javasrc/java/lang/Runtime.java =================================================================== --- vm/vmcore/src/kernel_classes/javasrc/java/lang/Runtime.java (revision 449690) +++ vm/vmcore/src/kernel_classes/javasrc/java/lang/Runtime.java (working copy) @@ -146,15 +146,16 @@ */ static void addShutdownHook(Thread hook) throws IllegalStateException, IllegalArgumentException { + if (hook.getState() != Thread.State.NEW) { + throw new IllegalArgumentException(); + } synchronized (hooksList) { if (hooksList.contains((Object) hook)) { throw new IllegalArgumentException(); } } - synchronized (Synchro.class) { - if (VMState > 0) { - throw new IllegalStateException(); - } + if (VMState > 0) { + throw new IllegalStateException(); } synchronized (hooksList) { hooksList.addElement((Object) hook); @@ -168,10 +169,8 @@ */ static boolean removeShutdownHook(Thread hook) throws IllegalStateException { - synchronized (Synchro.class) { - if (VMState > 0) { - throw new IllegalStateException(); - } + if (VMState > 0) { + throw new IllegalStateException(); } synchronized (hooksList) { return hooksList == null ? false : hooksList.removeElement((Object) hook); @@ -295,16 +294,11 @@ private final native void close0(long handle) throws IOException; public final synchronized void close() throws IOException { - if (streamHandle == -1) return; - - long handle = streamHandle; - streamHandle = -1; - close0(handle); + close0(streamHandle); } protected void finalize() throws Throwable { - if (streamHandle != -1) - close0(this.streamHandle); + close0(streamHandle); } } @@ -411,15 +405,11 @@ private final native void close0(long handle); public final synchronized void close() throws IOException { - if (streamHandle == -1) return; - long handle = streamHandle; - streamHandle = -1; - close0(handle); + close0(streamHandle); } protected void finalize() throws Throwable { - if (streamHandle != -1) - close0(this.streamHandle); + close0(streamHandle); } }