1/* 2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26#include <assert.h> 27#include "java_lang_ProcessImpl.h" 28 29#include "jni.h" 30#include "jvm.h" 31#include "jni_util.h" 32#include "io_util.h" 33#include "io_util_md.h" 34#include <windows.h> 35#include <io.h> 36 37/* We try to make sure that we can read and write 4095 bytes (the 38 * fixed limit on Linux) to the pipe on all operating systems without 39 * deadlock. Windows 2000 inexplicably appears to need an extra 24 40 * bytes of slop to avoid deadlock. 41 */ 42#define PIPE_SIZE (4096+24) 43 44/* We have THREE locales in action: 45 * 1. Thread default locale - dictates UNICODE-to-8bit conversion 46 * 2. System locale that defines the message localization 47 * 3. The file name locale 48 * Each locale could be an extended locale, that means that text cannot be 49 * mapped to 8bit sequence without multibyte encoding. 50 * VM is ready for that, if text is UTF-8. 51 * Here we make the work right from the beginning. 52 */ 53size_t os_error_message(int errnum, WCHAR* utf16_OSErrorMsg, size_t maxMsgLength) { 54 size_t n = (size_t)FormatMessageW( 55 FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 56 NULL, 57 (DWORD)errnum, 58 0, 59 utf16_OSErrorMsg, 60 (DWORD)maxMsgLength, 61 NULL); 62 if (n > 3) { 63 // Drop final '.', CR, LF 64 if (utf16_OSErrorMsg[n - 1] == L'\n') --n; 65 if (utf16_OSErrorMsg[n - 1] == L'\r') --n; 66 if (utf16_OSErrorMsg[n - 1] == L'.') --n; 67 utf16_OSErrorMsg[n] = L'\0'; 68 } 69 return n; 70} 71 72#define MESSAGE_LENGTH (256 + 100) 73#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x)) 74 75static void 76win32Error(JNIEnv *env, const WCHAR *functionName) 77{ 78 WCHAR utf16_OSErrorMsg[MESSAGE_LENGTH - 100]; 79 WCHAR utf16_javaMessage[MESSAGE_LENGTH]; 80 /*Good suggestion about 2-bytes-per-symbol in localized error reports*/ 81 char utf8_javaMessage[MESSAGE_LENGTH*2]; 82 const int errnum = (int)GetLastError(); 83 size_t n = os_error_message(errnum, utf16_OSErrorMsg, ARRAY_SIZE(utf16_OSErrorMsg)); 84 n = (n > 0) 85 ? swprintf(utf16_javaMessage, MESSAGE_LENGTH, L"%s error=%d, %s", functionName, errnum, utf16_OSErrorMsg) 86 : swprintf(utf16_javaMessage, MESSAGE_LENGTH, L"%s failed, error=%d", functionName, errnum); 87 88 if (n > 0) /*terminate '\0' is not a part of conversion procedure*/ 89 n = WideCharToMultiByte( 90 CP_UTF8, 91 0, 92 utf16_javaMessage, 93 (int)n, /*by creation n <= MESSAGE_LENGTH*/ 94 utf8_javaMessage, 95 MESSAGE_LENGTH*2, 96 NULL, 97 NULL); 98 99 /*no way to die*/ 100 { 101 const char *errorMessage = "Secondary error while OS message extraction"; 102 if (n > 0) { 103 utf8_javaMessage[min(MESSAGE_LENGTH*2 - 1, n)] = '\0'; 104 errorMessage = utf8_javaMessage; 105 } 106 JNU_ThrowIOException(env, errorMessage); 107 } 108} 109 110static void 111closeSafely(HANDLE handle) 112{ 113 if (handle != INVALID_HANDLE_VALUE) 114 CloseHandle(handle); 115} 116 117static BOOL hasInheritFlag(HANDLE handle) 118{ 119 DWORD mask; 120 if (GetHandleInformation(handle, &mask)) { 121 return mask & HANDLE_FLAG_INHERIT; 122 } 123 return FALSE; 124} 125 126#define HANDLE_STORAGE_SIZE 6 127#define OFFSET_READ 0 128#define OFFSET_WRITE 1 129//long signed version of INVALID_HANDLE_VALUE 130#define JAVA_INVALID_HANDLE_VALUE ((jlong) -1) 131#define OPPOSITE_END(offset) (offset==OFFSET_READ ? OFFSET_WRITE : OFFSET_READ) 132 133/* Pipe holder structure */ 134typedef struct _STDHOLDER { 135 HANDLE pipe[2]; 136 int offset; 137} STDHOLDER; 138 139/* Responsible for correct initialization of the [pHolder] structure 140 (that is used for handles recycling) if needs, 141 and appropriate setup of IOE handle [phStd] for child process based 142 on created pipe or Java handle. */ 143static BOOL initHolder( 144 JNIEnv *env, 145 jlong *pjhandles, /* IN OUT - the handle form Java, 146 that can be a file, console or undefined */ 147 STDHOLDER *pHolder, /* OUT - initialized structure that holds pipe 148 handles */ 149 HANDLE *phStd /* OUT - initialized handle for child process */ 150) { 151 /* Here we test the value from Java against invalid 152 handle value. We are not using INVALID_HANDLE_VALUE macro 153 due to double signed/unsigned and 32/64bit ambiguity. 154 Otherwise it will be easy to get the wrong 155 value 0x00000000FFFFFFFF 156 instead 0xFFFFFFFFFFFFFFFF. */ 157 if (*pjhandles != JAVA_INVALID_HANDLE_VALUE) { 158 /* Java file or console redirection */ 159 *phStd = (HANDLE) *pjhandles; 160 /* Here we set the related Java stream (Process.getXXXXStream()) 161 to [ProcessBuilder.NullXXXXStream.INSTANCE] value. 162 The initial Java handle [*pjhandles] will be closed in 163 ANY case. It is not a handle leak. */ 164 *pjhandles = JAVA_INVALID_HANDLE_VALUE; 165 } else { 166 /* Creation of parent-child pipe */ 167 if (!CreatePipe( 168 &pHolder->pipe[OFFSET_READ], 169 &pHolder->pipe[OFFSET_WRITE], 170 NULL, /* we would like to inherit 171 default process access, 172 instead of 'Everybody' access */ 173 PIPE_SIZE)) 174 { 175 win32Error(env, L"CreatePipe"); 176 return FALSE; 177 } else { 178 /* [thisProcessEnd] has no the inherit flag because 179 the [lpPipeAttributes] param of [CreatePipe] 180 had the NULL value. */ 181 HANDLE thisProcessEnd = pHolder->pipe[OPPOSITE_END(pHolder->offset)]; 182 *phStd = pHolder->pipe[pHolder->offset]; 183 *pjhandles = (jlong) thisProcessEnd; 184 } 185 } 186 /* Pipe handle will be closed in the [releaseHolder] call, 187 file handle will be closed in Java. 188 The long-live handle need to restore the inherit flag, 189 we do it later in the [prepareIOEHandleState] call. */ 190 SetHandleInformation( 191 *phStd, 192 HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); 193 return TRUE; 194} 195 196/* Smart recycling of pipe handles in [pHolder]. For the failed 197 create process attempts, both ends of pipe need to be released. 198 The [complete] has the [TRUE] value in the failed attempt. */ 199static void releaseHolder(BOOL complete, STDHOLDER *pHolder) { 200 closeSafely(pHolder->pipe[pHolder->offset]); 201 if (complete) { 202 /* Error occur, close this process pipe end */ 203 closeSafely(pHolder->pipe[OPPOSITE_END(pHolder->offset)]); 204 } 205} 206 207/* Stores and drops the inherit flag of handles that should not 208 be shared with the child process by default, but can hold the 209 inherit flag due to MS process birth specific. */ 210static void prepareIOEHandleState( 211 HANDLE *stdIOE, 212 BOOL *inherit) 213{ 214 int i; 215 for (i = 0; i < HANDLE_STORAGE_SIZE; ++i) { 216 HANDLE hstd = stdIOE[i]; 217 if (INVALID_HANDLE_VALUE != hstd && hasInheritFlag(hstd)) { 218 /* FALSE by default */ 219 inherit[i] = TRUE; 220 /* Java does not need implicit inheritance for IOE handles, 221 so we drop inherit flag that probably was installed by 222 previous CreateProcess call that launched current process. 223 We will return the handle state back after CreateProcess call. 224 By clearing inherit flag we prevent "greedy grandchild" birth. 225 The explicit inheritance for child process IOE handles is 226 implemented in the [initHolder] call. */ 227 SetHandleInformation(hstd, HANDLE_FLAG_INHERIT, 0); 228 } 229 } 230} 231 232/* Restores the inheritance flag of handles from stored values. */ 233static void restoreIOEHandleState( 234 const HANDLE *stdIOE, 235 const BOOL *inherit) 236{ 237 /* The set of current process standard IOE handles and 238 the set of child process IOE handles can intersect. 239 To restore the inherit flag right, we use backward 240 array iteration. */ 241 int i; 242 for (i = HANDLE_STORAGE_SIZE - 1; i >= 0; --i) 243 if (INVALID_HANDLE_VALUE != stdIOE[i]) { 244 /* Restore inherit flag for any case. 245 The handle can be changed by explicit inheritance.*/ 246 SetHandleInformation(stdIOE[i], 247 HANDLE_FLAG_INHERIT, 248 inherit[i] ? HANDLE_FLAG_INHERIT : 0); 249 } 250} 251 252/* 253 * Class: java_lang_ProcessImpl 254 * Method: getProcessId0 255 * Signature: (J)I 256 */ 257JNIEXPORT jint JNICALL Java_java_lang_ProcessImpl_getProcessId0 258 (JNIEnv *env, jclass clazz, jlong handle) { 259 DWORD pid = GetProcessId((HANDLE) jlong_to_ptr(handle)); 260 return (jint)pid; 261} 262 263/* Please, read about the MS inheritance problem 264 http://support.microsoft.com/kb/315939 265 and critical section/synchronized block solution. */ 266static jlong processCreate( 267 JNIEnv *env, 268 const jchar *pcmd, 269 const jchar *penvBlock, 270 const jchar *pdir, 271 jlong *handles, 272 jboolean redirectErrorStream) 273{ 274 jlong ret = 0L; 275 STARTUPINFOW si = {sizeof(si)}; 276 277 /* Handles for which the inheritance flag must be restored. */ 278 HANDLE stdIOE[HANDLE_STORAGE_SIZE] = { 279 /* Current process standard IOE handles: JDK-7147084 */ 280 INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 281 /* Child process IOE handles: JDK-6921885 */ 282 (HANDLE)handles[0], (HANDLE)handles[1], (HANDLE)handles[2]}; 283 BOOL inherit[HANDLE_STORAGE_SIZE] = { 284 FALSE, FALSE, FALSE, 285 FALSE, FALSE, FALSE}; 286 287 /* These three should not be closed by CloseHandle! */ 288 stdIOE[0] = GetStdHandle(STD_INPUT_HANDLE); 289 stdIOE[1] = GetStdHandle(STD_OUTPUT_HANDLE); 290 stdIOE[2] = GetStdHandle(STD_ERROR_HANDLE); 291 292 prepareIOEHandleState(stdIOE, inherit); 293 { 294 /* Input */ 295 STDHOLDER holderIn = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_READ}; 296 if (initHolder(env, &handles[0], &holderIn, &si.hStdInput)) { 297 298 /* Output */ 299 STDHOLDER holderOut = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_WRITE}; 300 if (initHolder(env, &handles[1], &holderOut, &si.hStdOutput)) { 301 302 /* Error */ 303 STDHOLDER holderErr = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_WRITE}; 304 BOOL success; 305 if (redirectErrorStream) { 306 si.hStdError = si.hStdOutput; 307 /* Here we set the error stream to [ProcessBuilder.NullInputStream.INSTANCE] 308 value. That is in accordance with Java Doc for the redirection case. 309 The Java file for the [ handles[2] ] will be closed in ANY case. It is not 310 a handle leak. */ 311 handles[2] = JAVA_INVALID_HANDLE_VALUE; 312 success = TRUE; 313 } else { 314 success = initHolder(env, &handles[2], &holderErr, &si.hStdError); 315 } 316 317 if (success) { 318 PROCESS_INFORMATION pi; 319 DWORD processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT; 320 321 /* If the standard I/O is inherited, CREATE_NO_WINDOW must not be used. */ 322 if (GetConsoleWindow() != NULL && 323 (si.hStdInput == stdIOE[0] || 324 si.hStdOutput == stdIOE[1] || 325 si.hStdError == (redirectErrorStream ? stdIOE[1] : stdIOE[2]))) 326 { 327 processFlag &= ~CREATE_NO_WINDOW; 328 } 329 330 si.dwFlags = STARTF_USESTDHANDLES; 331 if (!CreateProcessW( 332 NULL, /* executable name */ 333 (LPWSTR)pcmd, /* command line */ 334 NULL, /* process security attribute */ 335 NULL, /* thread security attribute */ 336 TRUE, /* inherits system handles */ 337 processFlag, /* selected based on exe type */ 338 (LPVOID)penvBlock,/* environment block */ 339 (LPCWSTR)pdir, /* change to the new current directory */ 340 &si, /* (in) startup information */ 341 &pi)) /* (out) process information */ 342 { 343 win32Error(env, L"CreateProcess"); 344 } else { 345 closeSafely(pi.hThread); 346 ret = (jlong)pi.hProcess; 347 } 348 } 349 releaseHolder(ret == 0, &holderErr); 350 releaseHolder(ret == 0, &holderOut); 351 } 352 releaseHolder(ret == 0, &holderIn); 353 } 354 } 355 restoreIOEHandleState(stdIOE, inherit); 356 357 return ret; 358} 359 360JNIEXPORT jlong JNICALL 361Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored, 362 jstring cmd, 363 jstring envBlock, 364 jstring dir, 365 jlongArray stdHandles, 366 jboolean redirectErrorStream) 367{ 368 jlong ret = 0; 369 if (cmd != NULL && stdHandles != NULL) { 370 const jchar *pcmd = (*env)->GetStringChars(env, cmd, NULL); 371 if (pcmd != NULL) { 372 const jchar *penvBlock = (envBlock != NULL) 373 ? (*env)->GetStringChars(env, envBlock, NULL) 374 : NULL; 375 if (!(*env)->ExceptionCheck(env)) { 376 const jchar *pdir = (dir != NULL) 377 ? (*env)->GetStringChars(env, dir, NULL) 378 : NULL; 379 if (!(*env)->ExceptionCheck(env)) { 380 jlong *handles = (*env)->GetLongArrayElements(env, stdHandles, NULL); 381 if (handles != NULL) { 382 ret = processCreate( 383 env, 384 pcmd, 385 penvBlock, 386 pdir, 387 handles, 388 redirectErrorStream); 389 (*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0); 390 } 391 if (pdir != NULL) 392 (*env)->ReleaseStringChars(env, dir, pdir); 393 } 394 if (penvBlock != NULL) 395 (*env)->ReleaseStringChars(env, envBlock, penvBlock); 396 } 397 (*env)->ReleaseStringChars(env, cmd, pcmd); 398 } 399 } 400 return ret; 401} 402 403JNIEXPORT jint JNICALL 404Java_java_lang_ProcessImpl_getExitCodeProcess(JNIEnv *env, jclass ignored, jlong handle) 405{ 406 DWORD exit_code; 407 if (GetExitCodeProcess((HANDLE) handle, &exit_code) == 0) 408 win32Error(env, L"GetExitCodeProcess"); 409 return exit_code; 410} 411 412JNIEXPORT jint JNICALL 413Java_java_lang_ProcessImpl_getStillActive(JNIEnv *env, jclass ignored) 414{ 415 return STILL_ACTIVE; 416} 417 418JNIEXPORT void JNICALL 419Java_java_lang_ProcessImpl_waitForInterruptibly(JNIEnv *env, jclass ignored, jlong handle) 420{ 421 HANDLE events[2]; 422 events[0] = (HANDLE) handle; 423 events[1] = JVM_GetThreadInterruptEvent(); 424 425 if (WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events, 426 FALSE, /* Wait for ANY event */ 427 INFINITE) /* Wait forever */ 428 == WAIT_FAILED) 429 win32Error(env, L"WaitForMultipleObjects"); 430} 431 432JNIEXPORT void JNICALL 433Java_java_lang_ProcessImpl_waitForTimeoutInterruptibly(JNIEnv *env, 434 jclass ignored, 435 jlong handle, 436 jlong timeout) 437{ 438 HANDLE events[2]; 439 DWORD dwTimeout = (DWORD)timeout; 440 DWORD result; 441 events[0] = (HANDLE) handle; 442 events[1] = JVM_GetThreadInterruptEvent(); 443 result = WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events, 444 FALSE, /* Wait for ANY event */ 445 dwTimeout); /* Wait for dwTimeout */ 446 447 if (result == WAIT_FAILED) 448 win32Error(env, L"WaitForMultipleObjects"); 449} 450 451JNIEXPORT void JNICALL 452Java_java_lang_ProcessImpl_terminateProcess(JNIEnv *env, jclass ignored, jlong handle) 453{ 454 TerminateProcess((HANDLE) handle, 1); 455} 456 457JNIEXPORT jboolean JNICALL 458Java_java_lang_ProcessImpl_isProcessAlive(JNIEnv *env, jclass ignored, jlong handle) 459{ 460 DWORD dwExitStatus; 461 GetExitCodeProcess((HANDLE) handle, &dwExitStatus); 462 return dwExitStatus == STILL_ACTIVE; 463} 464 465JNIEXPORT jboolean JNICALL 466Java_java_lang_ProcessImpl_closeHandle(JNIEnv *env, jclass ignored, jlong handle) 467{ 468 return (jboolean) CloseHandle((HANDLE) handle); 469} 470 471JNIEXPORT jlong JNICALL 472Java_java_lang_ProcessImpl_openForAtomicAppend(JNIEnv *env, jclass ignored, jstring path) 473{ 474 const DWORD access = (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA); 475 const DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; 476 const DWORD disposition = OPEN_ALWAYS; 477 const DWORD flagsAndAttributes = FILE_ATTRIBUTE_NORMAL; 478 HANDLE h; 479 WCHAR *pathbuf = pathToNTPath(env, path, JNI_FALSE); 480 if (pathbuf == NULL) { 481 /* Exception already pending */ 482 return -1; 483 } 484 h = CreateFileW( 485 pathbuf, /* Wide char path name */ 486 access, /* Read and/or write permission */ 487 sharing, /* File sharing flags */ 488 NULL, /* Security attributes */ 489 disposition, /* creation disposition */ 490 flagsAndAttributes, /* flags and attributes */ 491 NULL); 492 free(pathbuf); 493 if (h == INVALID_HANDLE_VALUE) { 494 JNU_ThrowIOExceptionWithLastError(env, "CreateFileW"); 495 } 496 return ptr_to_jlong(h); 497} 498