src/windows/native/java/lang/ProcessImpl_md.c

Print this page
rev 7704 : 8016579: (process) IOException thrown by ProcessBuilder.start() method is incorrectly encoded

*** 110,133 **** JNU_ReleaseStringPlatformChars(env, cmd0, exe); } return newFlag; } static void ! win32Error(JNIEnv *env, const char *functionName) { ! static const char * const format = "%s error=%d, %s"; ! static const char * const fallbackFormat = "%s failed, error=%d"; ! char buf[256]; ! char errmsg[sizeof(buf) + 100]; ! const int errnum = GetLastError(); ! const int n = JVM_GetLastErrorString(buf, sizeof(buf)); ! if (n > 0) ! sprintf(errmsg, format, functionName, errnum, buf); ! else ! sprintf(errmsg, fallbackFormat, functionName, errnum); ! JNU_ThrowIOException(env, errmsg); } static void closeSafely(HANDLE handle) { --- 110,183 ---- JNU_ReleaseStringPlatformChars(env, cmd0, exe); } return newFlag; } + /* We have THREE locales in action: + * 1. Thread default locale - dictates UNICODE-to-8bit conversion + * 2. System locale that defines the message localization + * 3. The file name locale + * Each locale could be an extended locale, that means that text cannot be + * mapped to 8bit sequence without multibyte encoding. + * VM is ready for that, if text is UTF-8. + * Here we make the work right from the beginning. + */ + size_t os_error_message(int errnum, WCHAR* utf16_OSErrorMsg, size_t maxMsgLength) { + size_t n = (size_t)FormatMessageW( + FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + (DWORD)errnum, + 0, + utf16_OSErrorMsg, + (DWORD)maxMsgLength, + NULL); + if (n > 3) { + // Drop final '.', CR, LF + if (utf16_OSErrorMsg[n - 1] == L'\n') --n; + if (utf16_OSErrorMsg[n - 1] == L'\r') --n; + if (utf16_OSErrorMsg[n - 1] == L'.') --n; + utf16_OSErrorMsg[n] = L'\0'; + } + return n; + } + + #define MESSAGE_LENGTH (256 + 100) + #define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x)) + static void ! win32Error(JNIEnv *env, const WCHAR *functionName) { ! WCHAR utf16_OSErrorMsg[MESSAGE_LENGTH - 100]; ! WCHAR utf16_javaMessage[MESSAGE_LENGTH]; ! /*Good suggestion about 2-bytes-per-symbol in localized error reports*/ ! char utf8_javaMessage[MESSAGE_LENGTH*2]; ! const int errnum = (int)GetLastError(); ! int n = os_error_message(errnum, utf16_OSErrorMsg, ARRAY_SIZE(utf16_OSErrorMsg)); ! n = (n > 0) ! ? swprintf(utf16_javaMessage, MESSAGE_LENGTH, L"%s error=%d, %s", functionName, errnum, utf16_OSErrorMsg) ! : swprintf(utf16_javaMessage, MESSAGE_LENGTH, L"%s failed, error=%d", functionName, errnum); ! ! if (n > 0) /*terminate '\0' is not a part of conversion procedure*/ ! n = WideCharToMultiByte( ! CP_UTF8, ! 0, ! utf16_javaMessage, ! n, /*by creation n <= MESSAGE_LENGTH*/ ! utf8_javaMessage, ! MESSAGE_LENGTH*2, ! NULL, ! NULL); ! ! /*no way to die*/ ! { ! const char *errorMessage = "Secondary error while OS message extraction"; ! if (n > 0) { ! utf8_javaMessage[min(MESSAGE_LENGTH*2 - 1, n)] = '\0'; ! errorMessage = utf8_javaMessage; ! } ! JNU_ThrowIOException(env, errorMessage); ! } } static void closeSafely(HANDLE handle) {
*** 191,201 **** 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 because the [lpPipeAttributes] param of [CreatePipe] had the NULL value. */ --- 241,251 ---- NULL, /* we would like to inherit default process access, instead of 'Everybody' access */ PIPE_SIZE)) { ! win32Error(env, L"CreatePipe"); return FALSE; } else { /* [thisProcessEnd] has no the inherit flag because the [lpPipeAttributes] param of [CreatePipe] had the NULL value. */
*** 347,357 **** (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; } } --- 397,407 ---- (LPVOID)penvBlock,/* environment block */ (LPCWSTR)pdir, /* change to the new current directory */ &si, /* (in) startup information */ &pi)) /* (out) process information */ { ! win32Error(env, L"CreateProcess"); } else { closeSafely(pi.hThread); ret = (jlong)pi.hProcess; } }
*** 408,418 **** JNIEXPORT jint JNICALL Java_java_lang_ProcessImpl_getExitCodeProcess(JNIEnv *env, jclass ignored, jlong handle) { DWORD exit_code; if (GetExitCodeProcess((HANDLE) handle, &exit_code) == 0) ! win32Error(env, "GetExitCodeProcess"); return exit_code; } JNIEXPORT jint JNICALL Java_java_lang_ProcessImpl_getStillActive(JNIEnv *env, jclass ignored) --- 458,468 ---- JNIEXPORT jint JNICALL Java_java_lang_ProcessImpl_getExitCodeProcess(JNIEnv *env, jclass ignored, jlong handle) { DWORD exit_code; if (GetExitCodeProcess((HANDLE) handle, &exit_code) == 0) ! win32Error(env, L"GetExitCodeProcess"); return exit_code; } JNIEXPORT jint JNICALL Java_java_lang_ProcessImpl_getStillActive(JNIEnv *env, jclass ignored)
*** 429,439 **** if (WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events, FALSE, /* Wait for ANY event */ INFINITE) /* Wait forever */ == WAIT_FAILED) ! win32Error(env, "WaitForMultipleObjects"); } JNIEXPORT void JNICALL Java_java_lang_ProcessImpl_terminateProcess(JNIEnv *env, jclass ignored, jlong handle) { --- 479,489 ---- if (WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events, FALSE, /* Wait for ANY event */ INFINITE) /* Wait forever */ == WAIT_FAILED) ! win32Error(env, L"WaitForMultipleObjects"); } JNIEXPORT void JNICALL Java_java_lang_ProcessImpl_terminateProcess(JNIEnv *env, jclass ignored, jlong handle) {