1 /* 2 * Copyright (c) 1997, 2013, 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 <windows.h> 34 #include <io.h> 35 36 /* We try to make sure that we can read and write 4095 bytes (the 37 * fixed limit on Linux) to the pipe on all operating systems without 38 * deadlock. Windows 2000 inexplicably appears to need an extra 24 39 * bytes of slop to avoid deadlock. 40 */ 41 #define PIPE_SIZE (4096+24) 42 43 char * 44 extractExecutablePath(JNIEnv *env, char *source) 45 { 46 char *p, *r; 47 48 /* If no spaces, then use entire thing */ 49 if ((p = strchr(source, ' ')) == NULL) 50 return source; 51 52 /* If no quotes, or quotes after space, return up to space */ 53 if (((r = strchr(source, '"')) == NULL) || (r > p)) { 54 *p = 0; 55 return source; 56 } 57 58 /* Quotes before space, return up to space after next quotes */ 59 p = strchr(r, '"'); 60 if ((p = strchr(p, ' ')) == NULL) 61 return source; 62 *p = 0; 63 return source; 64 } 65 66 static const char EXE_EXT[] = ".exe"; 67 68 DWORD 69 selectProcessFlag(JNIEnv *env, jstring cmd0) 70 { 71 DWORD newFlag = 0; 72 char *exe = (char *)JNU_GetStringPlatformChars(env, cmd0, 0); 73 if (exe != NULL) { 74 char buf[MAX_PATH]; 75 char *name; 76 DWORD len; 77 exe = extractExecutablePath(env, exe); 78 if (exe != NULL) { 79 /* We are here for Win9x/Me, so the [/] is not the path sep */ 80 char *p = strrchr(exe, '\\'); 81 if (p == NULL) { 82 len = SearchPath(NULL, exe, EXE_EXT, MAX_PATH, buf, &name); 83 } else { 84 *p = 0; 85 len = SearchPath(exe, p + 1, EXE_EXT, MAX_PATH, buf, &name); 86 } 87 } 88 89 if (len > 0 && len < MAX_PATH) { 90 /* Here the [buf] path is valid and null terminated */ 91 int fd = _open(buf, _O_RDONLY); 92 if (fd != -1) { 93 unsigned char buffer[2]; 94 if (_read(fd, buffer, 2) == 2 95 && buffer[0] == 'M' && buffer[1] == 'Z' 96 && _lseek(fd, 60L, SEEK_SET) == 60L 97 && _read(fd, buffer, 2) == 2) 98 { 99 long headerLoc = (long)buffer[1] << 8 | (long)buffer[0]; 100 if (_lseek(fd, headerLoc, SEEK_SET) == headerLoc 101 && _read(fd, buffer, 2) == 2 102 && buffer[0] == 'P' && buffer[1] == 'E') 103 { 104 newFlag = DETACHED_PROCESS; 105 } 106 } 107 _close(fd); 108 } 109 } 110 JNU_ReleaseStringPlatformChars(env, cmd0, exe); 111 } 112 return newFlag; 113 } 114 115 static void 116 win32Error(JNIEnv *env, const char *functionName) 117 { 118 static const char * const format = "%s error=%d, %s"; 119 static const char * const fallbackFormat = "%s failed, error=%d"; 120 char buf[256]; 121 char errmsg[sizeof(buf) + 100]; 122 const int errnum = GetLastError(); 123 const int n = JVM_GetLastErrorString(buf, sizeof(buf)); 124 if (n > 0) 125 sprintf(errmsg, format, functionName, errnum, buf); 126 else 127 sprintf(errmsg, fallbackFormat, functionName, errnum); 128 JNU_ThrowIOException(env, errmsg); 129 } 130 131 static void 132 closeSafely(HANDLE handle) 133 { 134 if (handle != INVALID_HANDLE_VALUE) 135 CloseHandle(handle); 136 } 137 138 static BOOL hasInheritFlag(HANDLE handle) 139 { 140 DWORD mask; 141 if (GetHandleInformation(handle, &mask)) { 142 return mask & HANDLE_FLAG_INHERIT; 143 } 144 return FALSE; 145 } 146 147 #define HANDLE_STORAGE_SIZE 6 148 #define OFFSET_READ 0 149 #define OFFSET_WRITE 1 150 //long signed version of INVALID_HANDLE_VALUE 151 #define JAVA_INVALID_HANDLE_VALUE ((jlong) -1) 152 #define OPPOSITE_END(offset) (offset==OFFSET_READ ? OFFSET_WRITE : OFFSET_READ) 153 154 /* Pipe holder structure */ 155 typedef struct _STDHOLDER { 156 HANDLE pipe[2]; 157 int offset; 158 } STDHOLDER; 159 160 /* Responsible for correct initialization of the [pHolder] structure 161 (that is used for handles recycling) if needs, 162 and appropriate setup of IOE handle [phStd] for child process based 163 on created pipe or Java handle. */ 164 static BOOL initHolder( 165 JNIEnv *env, 166 jlong *pjhandles, /* IN OUT - the handle form Java, 167 that can be a file, console or undefined */ 168 STDHOLDER *pHolder, /* OUT - initialized structure that holds pipe 169 handles */ 170 HANDLE *phStd /* OUT - initialized handle for child process */ 171 ) { 172 /* Here we test the value from Java against invalid 173 handle value. We are not using INVALID_HANDLE_VALUE macro 174 due to double signed/unsigned and 32/64bit ambiguity. 175 Otherwise it will be easy to get the wrong 176 value 0x00000000FFFFFFFF 177 instead 0xFFFFFFFFFFFFFFFF. */ 178 if (*pjhandles != JAVA_INVALID_HANDLE_VALUE) { 179 /* Java file or console redirection */ 180 *phStd = (HANDLE) *pjhandles; 181 /* Here we set the related Java stream (Process.getXXXXStream()) 182 to [ProcessBuilder.NullXXXXStream.INSTANCE] value. 183 The initial Java handle [*pjhandles] will be closed in 184 ANY case. It is not a handle leak. */ 185 *pjhandles = JAVA_INVALID_HANDLE_VALUE; 186 } else { 187 /* Creation of parent-child pipe */ 188 if (!CreatePipe( 189 &pHolder->pipe[OFFSET_READ], 190 &pHolder->pipe[OFFSET_WRITE], 191 NULL, /* we would like to inherit 192 default process access, 193 instead of 'Everybody' access */ 194 PIPE_SIZE)) 195 { 196 win32Error(env, "CreatePipe"); 197 return FALSE; 198 } else { 199 /* [thisProcessEnd] has no the inherit flag because 200 the [lpPipeAttributes] param of [CreatePipe] 201 had the NULL value. */ 202 HANDLE thisProcessEnd = pHolder->pipe[OPPOSITE_END(pHolder->offset)]; 203 *phStd = pHolder->pipe[pHolder->offset]; 204 *pjhandles = (jlong) thisProcessEnd; 205 } 206 } 207 /* Pipe handle will be closed in the [releaseHolder] call, 208 file handle will be closed in Java. 209 The long-live handle need to restore the inherit flag, 210 we do it later in the [prepareIOEHandleState] call. */ 211 SetHandleInformation( 212 *phStd, 213 HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); 214 return TRUE; 215 } 216 217 /* Smart recycling of pipe handles in [pHolder]. For the failed 218 create process attempts, both ends of pipe need to be released. 219 The [complete] has the [TRUE] value in the failed attempt. */ 220 static void releaseHolder(BOOL complete, STDHOLDER *pHolder) { 221 closeSafely(pHolder->pipe[pHolder->offset]); 222 if (complete) { 223 /* Error occur, close this process pipe end */ 224 closeSafely(pHolder->pipe[OPPOSITE_END(pHolder->offset)]); 225 } 226 } 227 228 /* Stores and drops the inherit flag of handles that should not 229 be shared with the child process by default, but can hold the 230 inherit flag due to MS process birth specific. */ 231 static void prepareIOEHandleState( 232 HANDLE *stdIOE, 233 BOOL *inherit) 234 { 235 int i; 236 for (i = 0; i < HANDLE_STORAGE_SIZE; ++i) { 237 HANDLE hstd = stdIOE[i]; 238 if (INVALID_HANDLE_VALUE != hstd && hasInheritFlag(hstd)) { 239 /* FALSE by default */ 240 inherit[i] = TRUE; 241 /* Java does not need implicit inheritance for IOE handles, 242 so we drop inherit flag that probably was installed by 243 previous CreateProcess call that launched current process. 244 We will return the handle state back after CreateProcess call. 245 By clearing inherit flag we prevent "greedy grandchild" birth. 246 The explicit inheritance for child process IOE handles is 247 implemented in the [initHolder] call. */ 248 SetHandleInformation(hstd, HANDLE_FLAG_INHERIT, 0); 249 } 250 } 251 } 252 253 /* Restores the inheritance flag of handles from stored values. */ 254 static void restoreIOEHandleState( 255 const HANDLE *stdIOE, 256 const BOOL *inherit) 257 { 258 /* The set of current process standard IOE handles and 259 the set of child process IOE handles can intersect. 260 To restore the inherit flag right, we use backward 261 array iteration. */ 262 int i; 263 for (i = HANDLE_STORAGE_SIZE - 1; i >= 0; --i) 264 if (INVALID_HANDLE_VALUE != stdIOE[i]) { 265 /* Restore inherit flag for any case. 266 The handle can be changed by explicit inheritance.*/ 267 SetHandleInformation(stdIOE[i], 268 HANDLE_FLAG_INHERIT, 269 inherit[i] ? HANDLE_FLAG_INHERIT : 0); 270 } 271 } 272 273 /* Please, read about the MS inheritance problem 274 http://support.microsoft.com/kb/315939 275 and critical section/synchronized block solution. */ 276 static jlong processCreate( 277 JNIEnv *env, 278 const jchar *pcmd, 279 const jchar *penvBlock, 280 const jchar *pdir, 281 jlong *handles, 282 jboolean redirectErrorStream) 283 { 284 jlong ret = 0L; 285 STARTUPINFOW si = {sizeof(si)}; 286 287 /* Handles for which the inheritance flag must be restored. */ 288 HANDLE stdIOE[HANDLE_STORAGE_SIZE] = { 289 /* Current process standard IOE handles: JDK-7147084 */ 290 INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 291 /* Child process IOE handles: JDK-6921885 */ 292 (HANDLE)handles[0], (HANDLE)handles[1], (HANDLE)handles[2]}; 293 BOOL inherit[HANDLE_STORAGE_SIZE] = { 294 FALSE, FALSE, FALSE, 295 FALSE, FALSE, FALSE}; 296 297 { 298 /* Extraction of current process standard IOE handles */ 299 DWORD idsIOE[3] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE}; 300 int i; 301 for (i = 0; i < 3; ++i) 302 /* Should not be closed by CloseHandle! */ 303 stdIOE[i] = GetStdHandle(idsIOE[i]); 304 } 305 306 prepareIOEHandleState(stdIOE, inherit); 307 { 308 /* Input */ 309 STDHOLDER holderIn = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_READ}; 310 if (initHolder(env, &handles[0], &holderIn, &si.hStdInput)) { 311 312 /* Output */ 313 STDHOLDER holderOut = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_WRITE}; 314 if (initHolder(env, &handles[1], &holderOut, &si.hStdOutput)) { 315 316 /* Error */ 317 STDHOLDER holderErr = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_WRITE}; 318 BOOL success; 319 if (redirectErrorStream) { 320 si.hStdError = si.hStdOutput; 321 /* Here we set the error stream to [ProcessBuilder.NullInputStream.INSTANCE] 322 value. That is in accordance with Java Doc for the redirection case. 323 The Java file for the [ handles[2] ] will be closed in ANY case. It is not 324 a handle leak. */ 325 handles[2] = JAVA_INVALID_HANDLE_VALUE; 326 success = TRUE; 327 } else { 328 success = initHolder(env, &handles[2], &holderErr, &si.hStdError); 329 } 330 331 if (success) { 332 PROCESS_INFORMATION pi; 333 DWORD processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT; 334 335 si.dwFlags = STARTF_USESTDHANDLES; 336 if (!CreateProcessW( 337 NULL, /* executable name */ 338 (LPWSTR)pcmd, /* command line */ 339 NULL, /* process security attribute */ 340 NULL, /* thread security attribute */ 341 TRUE, /* inherits system handles */ 342 processFlag, /* selected based on exe type */ 343 (LPVOID)penvBlock,/* environment block */ 344 (LPCWSTR)pdir, /* change to the new current directory */ 345 &si, /* (in) startup information */ 346 &pi)) /* (out) process information */ 347 { 348 win32Error(env, "CreateProcess"); 349 } else { 350 closeSafely(pi.hThread); 351 ret = (jlong)pi.hProcess; 352 } 353 } 354 releaseHolder(ret == 0, &holderErr); 355 releaseHolder(ret == 0, &holderOut); 356 } 357 releaseHolder(ret == 0, &holderIn); 358 } 359 } 360 restoreIOEHandleState(stdIOE, inherit); 361 362 return ret; 363 } 364 365 JNIEXPORT jlong JNICALL 366 Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored, 367 jstring cmd, 368 jstring envBlock, 369 jstring dir, 370 jlongArray stdHandles, 371 jboolean redirectErrorStream) 372 { 373 jlong ret = 0; 374 if (cmd != NULL && stdHandles != NULL) { 375 const jchar *pcmd = (*env)->GetStringChars(env, cmd, NULL); 376 if (pcmd != NULL) { 377 const jchar *penvBlock = (envBlock != NULL) 378 ? (*env)->GetStringChars(env, envBlock, NULL) 379 : NULL; 380 const jchar *pdir = (dir != NULL) 381 ? (*env)->GetStringChars(env, dir, NULL) 382 : NULL; 383 jlong *handles = (*env)->GetLongArrayElements(env, stdHandles, NULL); 384 if (handles != NULL) { 385 ret = processCreate( 386 env, 387 pcmd, 388 penvBlock, 389 pdir, 390 handles, 391 redirectErrorStream); 392 (*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0); 393 } 394 if (pdir != NULL) 395 (*env)->ReleaseStringChars(env, dir, pdir); 396 if (penvBlock != NULL) 397 (*env)->ReleaseStringChars(env, envBlock, penvBlock); 398 (*env)->ReleaseStringChars(env, cmd, pcmd); 399 } 400 } 401 return ret; 402 } 403 404 JNIEXPORT jint JNICALL 405 Java_java_lang_ProcessImpl_getExitCodeProcess(JNIEnv *env, jclass ignored, jlong handle) 406 { 407 DWORD exit_code; 408 if (GetExitCodeProcess((HANDLE) handle, &exit_code) == 0) 409 win32Error(env, "GetExitCodeProcess"); 410 return exit_code; 411 } 412 413 JNIEXPORT jint JNICALL 414 Java_java_lang_ProcessImpl_getStillActive(JNIEnv *env, jclass ignored) 415 { 416 return STILL_ACTIVE; 417 } 418 419 JNIEXPORT void JNICALL 420 Java_java_lang_ProcessImpl_waitForInterruptibly(JNIEnv *env, jclass ignored, jlong handle) 421 { 422 HANDLE events[2]; 423 events[0] = (HANDLE) handle; 424 events[1] = JVM_GetThreadInterruptEvent(); 425 426 if (WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events, 427 FALSE, /* Wait for ANY event */ 428 INFINITE) /* Wait forever */ 429 == WAIT_FAILED) 430 win32Error(env, "WaitForMultipleObjects"); 431 } 432 433 JNIEXPORT void JNICALL 434 Java_java_lang_ProcessImpl_terminateProcess(JNIEnv *env, jclass ignored, jlong handle) 435 { 436 TerminateProcess((HANDLE) handle, 1); 437 } 438 439 JNIEXPORT jboolean JNICALL 440 Java_java_lang_ProcessImpl_closeHandle(JNIEnv *env, jclass ignored, jlong handle) 441 { 442 return CloseHandle((HANDLE) handle); 443 } 444 445 /** 446 * Returns a copy of the Unicode characters of a string. Fow now this 447 * function doesn't handle long path names and other issues. 448 */ 449 static WCHAR* getPath(JNIEnv *env, jstring ps) { 450 WCHAR *pathbuf = NULL; 451 const jchar *chars = (*(env))->GetStringChars(env, ps, NULL); 452 if (chars != NULL) { 453 size_t pathlen = wcslen(chars); 454 pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR)); 455 if (pathbuf == NULL) { 456 JNU_ThrowOutOfMemoryError(env, NULL); 457 } else { 458 wcscpy(pathbuf, chars); 459 } 460 (*env)->ReleaseStringChars(env, ps, chars); 461 } 462 return pathbuf; 463 } 464 465 JNIEXPORT jlong JNICALL 466 Java_java_lang_ProcessImpl_openForAtomicAppend(JNIEnv *env, jclass ignored, jstring path) 467 { 468 const DWORD access = (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA); 469 const DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; 470 const DWORD disposition = OPEN_ALWAYS; 471 const DWORD flagsAndAttributes = FILE_ATTRIBUTE_NORMAL; 472 HANDLE h; 473 WCHAR *pathbuf = getPath(env, path); 474 if (pathbuf == NULL) { 475 /* Exception already pending */ 476 return -1; 477 } 478 h = CreateFileW( 479 pathbuf, /* Wide char path name */ 480 access, /* Read and/or write permission */ 481 sharing, /* File sharing flags */ 482 NULL, /* Security attributes */ 483 disposition, /* creation disposition */ 484 flagsAndAttributes, /* flags and attributes */ 485 NULL); 486 free(pathbuf); 487 if (h == INVALID_HANDLE_VALUE) { 488 JNU_ThrowIOExceptionWithLastError(env, "CreateFileW"); 489 } 490 return ptr_to_jlong(h); 491 }