OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include <process.h> | 5 #include <process.h> |
6 | 6 |
7 #include "bin/builtin.h" | 7 #include "bin/builtin.h" |
8 #include "bin/process.h" | 8 #include "bin/process.h" |
9 #include "bin/eventhandler.h" | 9 #include "bin/eventhandler.h" |
10 #include "bin/log.h" | 10 #include "bin/log.h" |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 Log::PrintErr("FormatMessage failed %d\n", GetLastError()); | 312 Log::PrintErr("FormatMessage failed %d\n", GetLastError()); |
313 } | 313 } |
314 _snwprintf(message, kMaxMessageLength, L"OS Error %d", error_code); | 314 _snwprintf(message, kMaxMessageLength, L"OS Error %d", error_code); |
315 } | 315 } |
316 message[kMaxMessageLength - 1] = '\0'; | 316 message[kMaxMessageLength - 1] = '\0'; |
317 *os_error_message = StringUtils::WideToUtf8(message); | 317 *os_error_message = StringUtils::WideToUtf8(message); |
318 return error_code; | 318 return error_code; |
319 } | 319 } |
320 | 320 |
321 | 321 |
| 322 typedef BOOL (WINAPI *InitProcThreadAttrListFn)( |
| 323 LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD, PSIZE_T); |
| 324 |
| 325 typedef BOOL (WINAPI *UpdateProcThreadAttrFn)( |
| 326 LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD_PTR, |
| 327 PVOID, SIZE_T, PVOID, PSIZE_T); |
| 328 |
| 329 typedef VOID (WINAPI *DeleteProcThreadAttrListFn)( |
| 330 LPPROC_THREAD_ATTRIBUTE_LIST); |
| 331 |
| 332 |
| 333 static InitProcThreadAttrListFn init_proc_thread_attr_list = NULL; |
| 334 static UpdateProcThreadAttrFn update_proc_thread_attr = NULL; |
| 335 static DeleteProcThreadAttrListFn delete_proc_thread_attr_list = NULL; |
| 336 |
| 337 |
| 338 static bool EnsureInitialized() { |
| 339 static bool load_attempted = false; |
| 340 static dart::Mutex mutex; |
| 341 HMODULE kernel32_module = GetModuleHandle(L"kernel32.dll"); |
| 342 if (!load_attempted) { |
| 343 MutexLocker locker(&mutex); |
| 344 if (load_attempted) return delete_proc_thread_attr_list != NULL; |
| 345 init_proc_thread_attr_list = reinterpret_cast<InitProcThreadAttrListFn>( |
| 346 GetProcAddress(kernel32_module, "InitializeProcThreadAttributeList")); |
| 347 update_proc_thread_attr = |
| 348 reinterpret_cast<UpdateProcThreadAttrFn>( |
| 349 GetProcAddress(kernel32_module, "UpdateProcThreadAttribute")); |
| 350 delete_proc_thread_attr_list = reinterpret_cast<DeleteProcThreadAttrListFn>( |
| 351 reinterpret_cast<DeleteProcThreadAttrListFn>( |
| 352 GetProcAddress(kernel32_module, "DeleteProcThreadAttributeList"))); |
| 353 load_attempted = true; |
| 354 return delete_proc_thread_attr_list != NULL; |
| 355 } |
| 356 return delete_proc_thread_attr_list != NULL; |
| 357 } |
| 358 |
| 359 |
322 int Process::Start(const char* path, | 360 int Process::Start(const char* path, |
323 char* arguments[], | 361 char* arguments[], |
324 intptr_t arguments_length, | 362 intptr_t arguments_length, |
325 const char* working_directory, | 363 const char* working_directory, |
326 char* environment[], | 364 char* environment[], |
327 intptr_t environment_length, | 365 intptr_t environment_length, |
328 intptr_t* in, | 366 intptr_t* in, |
329 intptr_t* out, | 367 intptr_t* out, |
330 intptr_t* err, | 368 intptr_t* err, |
331 intptr_t* id, | 369 intptr_t* id, |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 | 430 |
393 // Setup info structures. | 431 // Setup info structures. |
394 STARTUPINFOEXW startup_info; | 432 STARTUPINFOEXW startup_info; |
395 ZeroMemory(&startup_info, sizeof(startup_info)); | 433 ZeroMemory(&startup_info, sizeof(startup_info)); |
396 startup_info.StartupInfo.cb = sizeof(startup_info); | 434 startup_info.StartupInfo.cb = sizeof(startup_info); |
397 startup_info.StartupInfo.hStdInput = stdin_handles[kReadHandle]; | 435 startup_info.StartupInfo.hStdInput = stdin_handles[kReadHandle]; |
398 startup_info.StartupInfo.hStdOutput = stdout_handles[kWriteHandle]; | 436 startup_info.StartupInfo.hStdOutput = stdout_handles[kWriteHandle]; |
399 startup_info.StartupInfo.hStdError = stderr_handles[kWriteHandle]; | 437 startup_info.StartupInfo.hStdError = stderr_handles[kWriteHandle]; |
400 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES; | 438 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES; |
401 | 439 |
402 // Setup the handles to inherit. We only want to inherit the three handles | 440 LPPROC_THREAD_ATTRIBUTE_LIST attribute_list = NULL; |
403 // for stdin, stdout and stderr. | 441 |
404 SIZE_T size = 0; | 442 bool supports_proc_thread_attr_lists = EnsureInitialized(); |
405 // The call to determine the size of an attribute list always fails with | 443 if (supports_proc_thread_attr_lists) { |
406 // ERROR_INSUFFICIENT_BUFFER and that error should be ignored. | 444 // Setup the handles to inherit. We only want to inherit the three handles |
407 if (!InitializeProcThreadAttributeList(NULL, 1, 0, &size) && | 445 // for stdin, stdout and stderr. |
408 GetLastError() != ERROR_INSUFFICIENT_BUFFER) { | 446 SIZE_T size = 0; |
409 int error_code = SetOsErrorMessage(os_error_message); | 447 // The call to determine the size of an attribute list always fails with |
410 CloseProcessPipes( | 448 // ERROR_INSUFFICIENT_BUFFER and that error should be ignored. |
411 stdin_handles, stdout_handles, stderr_handles, exit_handles); | 449 if (!init_proc_thread_attr_list(NULL, 1, 0, &size) && |
412 return error_code; | 450 GetLastError() != ERROR_INSUFFICIENT_BUFFER) { |
413 } | 451 int error_code = SetOsErrorMessage(os_error_message); |
414 LPPROC_THREAD_ATTRIBUTE_LIST attribute_list = | 452 CloseProcessPipes( |
415 reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(size)); | 453 stdin_handles, stdout_handles, stderr_handles, exit_handles); |
416 ZeroMemory(attribute_list, size); | 454 return error_code; |
417 if (!InitializeProcThreadAttributeList(attribute_list, 1, 0, &size)) { | 455 } |
418 int error_code = SetOsErrorMessage(os_error_message); | 456 attribute_list = |
419 CloseProcessPipes( | 457 reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(size)); |
420 stdin_handles, stdout_handles, stderr_handles, exit_handles); | 458 ZeroMemory(attribute_list, size); |
421 free(attribute_list); | 459 if (!init_proc_thread_attr_list(attribute_list, 1, 0, &size)) { |
422 return error_code; | 460 int error_code = SetOsErrorMessage(os_error_message); |
423 } | 461 CloseProcessPipes( |
424 static const int kNumInheritedHandles = 3; | 462 stdin_handles, stdout_handles, stderr_handles, exit_handles); |
425 HANDLE inherited_handles[kNumInheritedHandles] = | 463 free(attribute_list); |
426 { stdin_handles[kReadHandle], | 464 return error_code; |
427 stdout_handles[kWriteHandle], | 465 } |
428 stderr_handles[kWriteHandle] }; | 466 static const int kNumInheritedHandles = 3; |
429 if (!UpdateProcThreadAttribute(attribute_list, | 467 HANDLE inherited_handles[kNumInheritedHandles] = |
| 468 { stdin_handles[kReadHandle], |
| 469 stdout_handles[kWriteHandle], |
| 470 stderr_handles[kWriteHandle] }; |
| 471 if (!update_proc_thread_attr(attribute_list, |
430 0, | 472 0, |
431 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, | 473 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, |
432 inherited_handles, | 474 inherited_handles, |
433 kNumInheritedHandles * sizeof(HANDLE), | 475 kNumInheritedHandles * sizeof(HANDLE), |
434 NULL, | 476 NULL, |
435 NULL)) { | 477 NULL)) { |
436 DeleteProcThreadAttributeList(attribute_list); | 478 delete_proc_thread_attr_list(attribute_list); |
437 int error_code = SetOsErrorMessage(os_error_message); | 479 int error_code = SetOsErrorMessage(os_error_message); |
438 CloseProcessPipes( | 480 CloseProcessPipes( |
439 stdin_handles, stdout_handles, stderr_handles, exit_handles); | 481 stdin_handles, stdout_handles, stderr_handles, exit_handles); |
440 free(attribute_list); | 482 free(attribute_list); |
441 return error_code; | 483 return error_code; |
| 484 } |
| 485 startup_info.lpAttributeList = attribute_list; |
442 } | 486 } |
443 startup_info.lpAttributeList = attribute_list; | |
444 | 487 |
445 PROCESS_INFORMATION process_info; | 488 PROCESS_INFORMATION process_info; |
446 ZeroMemory(&process_info, sizeof(process_info)); | 489 ZeroMemory(&process_info, sizeof(process_info)); |
447 | 490 |
448 // Transform input strings to system format. | 491 // Transform input strings to system format. |
449 const wchar_t* system_path = StringUtils::Utf8ToWide(path); | 492 const wchar_t* system_path = StringUtils::Utf8ToWide(path); |
450 wchar_t** system_arguments = new wchar_t*[arguments_length]; | 493 wchar_t** system_arguments = new wchar_t*[arguments_length]; |
451 for (int i = 0; i < arguments_length; i++) { | 494 for (int i = 0; i < arguments_length; i++) { |
452 system_arguments[i] = StringUtils::Utf8ToWide(arguments[i]); | 495 system_arguments[i] = StringUtils::Utf8ToWide(arguments[i]); |
453 } | 496 } |
454 | 497 |
455 // Compute command-line length. | 498 // Compute command-line length. |
456 int command_line_length = wcslen(system_path); | 499 int command_line_length = wcslen(system_path); |
457 for (int i = 0; i < arguments_length; i++) { | 500 for (int i = 0; i < arguments_length; i++) { |
458 command_line_length += wcslen(system_arguments[i]); | 501 command_line_length += wcslen(system_arguments[i]); |
459 } | 502 } |
460 // Account for null termination and one space per argument. | 503 // Account for null termination and one space per argument. |
461 command_line_length += arguments_length + 1; | 504 command_line_length += arguments_length + 1; |
462 static const int kMaxCommandLineLength = 32768; | 505 static const int kMaxCommandLineLength = 32768; |
463 if (command_line_length > kMaxCommandLineLength) { | 506 if (command_line_length > kMaxCommandLineLength) { |
464 int error_code = SetOsErrorMessage(os_error_message); | 507 int error_code = SetOsErrorMessage(os_error_message); |
465 CloseProcessPipes( | 508 CloseProcessPipes( |
466 stdin_handles, stdout_handles, stderr_handles, exit_handles); | 509 stdin_handles, stdout_handles, stderr_handles, exit_handles); |
467 free(const_cast<wchar_t*>(system_path)); | 510 free(const_cast<wchar_t*>(system_path)); |
468 for (int i = 0; i < arguments_length; i++) free(system_arguments[i]); | 511 for (int i = 0; i < arguments_length; i++) free(system_arguments[i]); |
469 delete[] system_arguments; | 512 delete[] system_arguments; |
470 DeleteProcThreadAttributeList(attribute_list); | 513 if (supports_proc_thread_attr_lists) { |
471 free(attribute_list); | 514 delete_proc_thread_attr_list(attribute_list); |
| 515 free(attribute_list); |
| 516 } |
472 return error_code; | 517 return error_code; |
473 } | 518 } |
474 | 519 |
475 // Put together command-line string. | 520 // Put together command-line string. |
476 wchar_t* command_line = new wchar_t[command_line_length]; | 521 wchar_t* command_line = new wchar_t[command_line_length]; |
477 int len = 0; | 522 int len = 0; |
478 int remaining = command_line_length; | 523 int remaining = command_line_length; |
479 int written = _snwprintf(command_line + len, remaining, L"%s", system_path); | 524 int written = _snwprintf(command_line + len, remaining, L"%s", system_path); |
480 len += written; | 525 len += written; |
481 remaining -= written; | 526 remaining -= written; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
546 reinterpret_cast<STARTUPINFOW*>(&startup_info), | 591 reinterpret_cast<STARTUPINFOW*>(&startup_info), |
547 &process_info); | 592 &process_info); |
548 | 593 |
549 // Deallocate command-line and environment block strings. | 594 // Deallocate command-line and environment block strings. |
550 delete[] command_line; | 595 delete[] command_line; |
551 delete[] environment_block; | 596 delete[] environment_block; |
552 if (system_working_directory != NULL) { | 597 if (system_working_directory != NULL) { |
553 free(const_cast<wchar_t*>(system_working_directory)); | 598 free(const_cast<wchar_t*>(system_working_directory)); |
554 } | 599 } |
555 | 600 |
556 DeleteProcThreadAttributeList(attribute_list); | 601 if (supports_proc_thread_attr_lists) { |
557 free(attribute_list); | 602 delete_proc_thread_attr_list(attribute_list); |
| 603 free(attribute_list); |
| 604 } |
558 | 605 |
559 if (result == 0) { | 606 if (result == 0) { |
560 int error_code = SetOsErrorMessage(os_error_message); | 607 int error_code = SetOsErrorMessage(os_error_message); |
561 CloseProcessPipes( | 608 CloseProcessPipes( |
562 stdin_handles, stdout_handles, stderr_handles, exit_handles); | 609 stdin_handles, stdout_handles, stderr_handles, exit_handles); |
563 return error_code; | 610 return error_code; |
564 } | 611 } |
565 | 612 |
566 ProcessInfoList::AddProcess(process_info.dwProcessId, | 613 ProcessInfoList::AddProcess(process_info.dwProcessId, |
567 process_info.hProcess, | 614 process_info.hProcess, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 | 652 |
606 | 653 |
607 void Process::TerminateExitCodeHandler() { | 654 void Process::TerminateExitCodeHandler() { |
608 // Nothing needs to be done on Windows. | 655 // Nothing needs to be done on Windows. |
609 } | 656 } |
610 | 657 |
611 | 658 |
612 intptr_t Process::CurrentProcessId() { | 659 intptr_t Process::CurrentProcessId() { |
613 return static_cast<intptr_t>(GetCurrentProcessId()); | 660 return static_cast<intptr_t>(GetCurrentProcessId()); |
614 } | 661 } |
OLD | NEW |