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)
{