| 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 #if !defined(DART_IO_DISABLED) | 5 #if !defined(DART_IO_DISABLED) |
| 6 | 6 |
| 7 #include "platform/globals.h" | 7 #include "platform/globals.h" |
| 8 #if defined(HOST_OS_WINDOWS) | 8 #if defined(HOST_OS_WINDOWS) |
| 9 | 9 |
| 10 #include "bin/process.h" | 10 #include "bin/process.h" |
| 11 | 11 |
| 12 #include <process.h> // NOLINT |
| 12 #include <psapi.h> // NOLINT | 13 #include <psapi.h> // NOLINT |
| 13 #include <process.h> // NOLINT | |
| 14 | 14 |
| 15 #include "bin/builtin.h" | 15 #include "bin/builtin.h" |
| 16 #include "bin/dartutils.h" | 16 #include "bin/dartutils.h" |
| 17 #include "bin/eventhandler.h" | 17 #include "bin/eventhandler.h" |
| 18 #include "bin/lockers.h" | 18 #include "bin/lockers.h" |
| 19 #include "bin/log.h" | 19 #include "bin/log.h" |
| 20 #include "bin/socket.h" | 20 #include "bin/socket.h" |
| 21 #include "bin/thread.h" | 21 #include "bin/thread.h" |
| 22 #include "bin/utils.h" | 22 #include "bin/utils.h" |
| 23 #include "bin/utils_win.h" | 23 #include "bin/utils_win.h" |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 // with RegisterWaitForSingleObject. | 75 // with RegisterWaitForSingleObject. |
| 76 HANDLE wait_handle_; | 76 HANDLE wait_handle_; |
| 77 // File descriptor for pipe to report exit code. | 77 // File descriptor for pipe to report exit code. |
| 78 HANDLE exit_pipe_; | 78 HANDLE exit_pipe_; |
| 79 // Link to next ProcessInfo object in the singly-linked list. | 79 // Link to next ProcessInfo object in the singly-linked list. |
| 80 ProcessInfo* next_; | 80 ProcessInfo* next_; |
| 81 | 81 |
| 82 DISALLOW_COPY_AND_ASSIGN(ProcessInfo); | 82 DISALLOW_COPY_AND_ASSIGN(ProcessInfo); |
| 83 }; | 83 }; |
| 84 | 84 |
| 85 | |
| 86 // Singly-linked list of ProcessInfo objects for all active processes | 85 // Singly-linked list of ProcessInfo objects for all active processes |
| 87 // started from Dart. | 86 // started from Dart. |
| 88 class ProcessInfoList { | 87 class ProcessInfoList { |
| 89 public: | 88 public: |
| 90 static void AddProcess(DWORD pid, HANDLE handle, HANDLE pipe) { | 89 static void AddProcess(DWORD pid, HANDLE handle, HANDLE pipe) { |
| 91 // Register a callback to extract the exit code, when the process | 90 // Register a callback to extract the exit code, when the process |
| 92 // is signaled. The callback runs in a independent thread from the OS pool. | 91 // is signaled. The callback runs in a independent thread from the OS pool. |
| 93 // Because the callback depends on the process list containing | 92 // Because the callback depends on the process list containing |
| 94 // the process, lock the mutex until the process is added to the list. | 93 // the process, lock the mutex until the process is added to the list. |
| 95 MutexLocker locker(mutex_); | 94 MutexLocker locker(mutex_); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 // started from Dart code. | 193 // started from Dart code. |
| 195 static ProcessInfo* active_processes_; | 194 static ProcessInfo* active_processes_; |
| 196 // Mutex protecting all accesses to the linked list of active | 195 // Mutex protecting all accesses to the linked list of active |
| 197 // processes. | 196 // processes. |
| 198 static Mutex* mutex_; | 197 static Mutex* mutex_; |
| 199 | 198 |
| 200 DISALLOW_ALLOCATION(); | 199 DISALLOW_ALLOCATION(); |
| 201 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList); | 200 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList); |
| 202 }; | 201 }; |
| 203 | 202 |
| 204 | |
| 205 ProcessInfo* ProcessInfoList::active_processes_ = NULL; | 203 ProcessInfo* ProcessInfoList::active_processes_ = NULL; |
| 206 Mutex* ProcessInfoList::mutex_ = new Mutex(); | 204 Mutex* ProcessInfoList::mutex_ = new Mutex(); |
| 207 | 205 |
| 208 | |
| 209 // Types of pipes to create. | 206 // Types of pipes to create. |
| 210 enum NamedPipeType { kInheritRead, kInheritWrite, kInheritNone }; | 207 enum NamedPipeType { kInheritRead, kInheritWrite, kInheritNone }; |
| 211 | 208 |
| 212 | |
| 213 // Create a pipe for communicating with a new process. The handles array | 209 // Create a pipe for communicating with a new process. The handles array |
| 214 // will contain the read and write ends of the pipe. Based on the type | 210 // will contain the read and write ends of the pipe. Based on the type |
| 215 // one of the handles will be inheritable. | 211 // one of the handles will be inheritable. |
| 216 // NOTE: If this function returns false the handles might have been allocated | 212 // NOTE: If this function returns false the handles might have been allocated |
| 217 // and the caller should make sure to close them in case of an error. | 213 // and the caller should make sure to close them in case of an error. |
| 218 static bool CreateProcessPipe(HANDLE handles[2], | 214 static bool CreateProcessPipe(HANDLE handles[2], |
| 219 wchar_t* pipe_name, | 215 wchar_t* pipe_name, |
| 220 NamedPipeType type) { | 216 NamedPipeType type) { |
| 221 // Security attributes describing an inheritable handle. | 217 // Security attributes describing an inheritable handle. |
| 222 SECURITY_ATTRIBUTES inherit_handle; | 218 SECURITY_ATTRIBUTES inherit_handle; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 (type == kInheritWrite) ? &inherit_handle : NULL, OPEN_EXISTING, | 263 (type == kInheritWrite) ? &inherit_handle : NULL, OPEN_EXISTING, |
| 268 FILE_WRITE_ATTRIBUTES | FILE_FLAG_OVERLAPPED, NULL); | 264 FILE_WRITE_ATTRIBUTES | FILE_FLAG_OVERLAPPED, NULL); |
| 269 if (handles[kWriteHandle] == INVALID_HANDLE_VALUE) { | 265 if (handles[kWriteHandle] == INVALID_HANDLE_VALUE) { |
| 270 Log::PrintErr("CreateFile failed %d\n", GetLastError()); | 266 Log::PrintErr("CreateFile failed %d\n", GetLastError()); |
| 271 return false; | 267 return false; |
| 272 } | 268 } |
| 273 } | 269 } |
| 274 return true; | 270 return true; |
| 275 } | 271 } |
| 276 | 272 |
| 277 | |
| 278 static void CloseProcessPipe(HANDLE handles[2]) { | 273 static void CloseProcessPipe(HANDLE handles[2]) { |
| 279 for (int i = kReadHandle; i < kWriteHandle; i++) { | 274 for (int i = kReadHandle; i < kWriteHandle; i++) { |
| 280 if (handles[i] != INVALID_HANDLE_VALUE) { | 275 if (handles[i] != INVALID_HANDLE_VALUE) { |
| 281 if (!CloseHandle(handles[i])) { | 276 if (!CloseHandle(handles[i])) { |
| 282 Log::PrintErr("CloseHandle failed %d\n", GetLastError()); | 277 Log::PrintErr("CloseHandle failed %d\n", GetLastError()); |
| 283 } | 278 } |
| 284 handles[i] = INVALID_HANDLE_VALUE; | 279 handles[i] = INVALID_HANDLE_VALUE; |
| 285 } | 280 } |
| 286 } | 281 } |
| 287 } | 282 } |
| 288 | 283 |
| 289 | |
| 290 static void CloseProcessPipes(HANDLE handles1[2], | 284 static void CloseProcessPipes(HANDLE handles1[2], |
| 291 HANDLE handles2[2], | 285 HANDLE handles2[2], |
| 292 HANDLE handles3[2], | 286 HANDLE handles3[2], |
| 293 HANDLE handles4[2]) { | 287 HANDLE handles4[2]) { |
| 294 CloseProcessPipe(handles1); | 288 CloseProcessPipe(handles1); |
| 295 CloseProcessPipe(handles2); | 289 CloseProcessPipe(handles2); |
| 296 CloseProcessPipe(handles3); | 290 CloseProcessPipe(handles3); |
| 297 CloseProcessPipe(handles4); | 291 CloseProcessPipe(handles4); |
| 298 } | 292 } |
| 299 | 293 |
| 300 | |
| 301 static int SetOsErrorMessage(char** os_error_message) { | 294 static int SetOsErrorMessage(char** os_error_message) { |
| 302 int error_code = GetLastError(); | 295 int error_code = GetLastError(); |
| 303 const int kMaxMessageLength = 256; | 296 const int kMaxMessageLength = 256; |
| 304 wchar_t message[kMaxMessageLength]; | 297 wchar_t message[kMaxMessageLength]; |
| 305 FormatMessageIntoBuffer(error_code, message, kMaxMessageLength); | 298 FormatMessageIntoBuffer(error_code, message, kMaxMessageLength); |
| 306 *os_error_message = StringUtilsWin::WideToUtf8(message); | 299 *os_error_message = StringUtilsWin::WideToUtf8(message); |
| 307 return error_code; | 300 return error_code; |
| 308 } | 301 } |
| 309 | 302 |
| 310 | |
| 311 // Open an inheritable handle to NUL. | 303 // Open an inheritable handle to NUL. |
| 312 static HANDLE OpenNul() { | 304 static HANDLE OpenNul() { |
| 313 SECURITY_ATTRIBUTES inherit_handle; | 305 SECURITY_ATTRIBUTES inherit_handle; |
| 314 inherit_handle.nLength = sizeof(SECURITY_ATTRIBUTES); | 306 inherit_handle.nLength = sizeof(SECURITY_ATTRIBUTES); |
| 315 inherit_handle.bInheritHandle = TRUE; | 307 inherit_handle.bInheritHandle = TRUE; |
| 316 inherit_handle.lpSecurityDescriptor = NULL; | 308 inherit_handle.lpSecurityDescriptor = NULL; |
| 317 HANDLE nul = CreateFile(L"NUL", GENERIC_READ | GENERIC_WRITE, 0, | 309 HANDLE nul = CreateFile(L"NUL", GENERIC_READ | GENERIC_WRITE, 0, |
| 318 &inherit_handle, OPEN_EXISTING, 0, NULL); | 310 &inherit_handle, OPEN_EXISTING, 0, NULL); |
| 319 if (nul == INVALID_HANDLE_VALUE) { | 311 if (nul == INVALID_HANDLE_VALUE) { |
| 320 Log::PrintErr("CloseHandle failed %d\n", GetLastError()); | 312 Log::PrintErr("CloseHandle failed %d\n", GetLastError()); |
| 321 } | 313 } |
| 322 return nul; | 314 return nul; |
| 323 } | 315 } |
| 324 | 316 |
| 325 | |
| 326 typedef BOOL(WINAPI* InitProcThreadAttrListFn)(LPPROC_THREAD_ATTRIBUTE_LIST, | 317 typedef BOOL(WINAPI* InitProcThreadAttrListFn)(LPPROC_THREAD_ATTRIBUTE_LIST, |
| 327 DWORD, | 318 DWORD, |
| 328 DWORD, | 319 DWORD, |
| 329 PSIZE_T); | 320 PSIZE_T); |
| 330 | 321 |
| 331 typedef BOOL(WINAPI* UpdateProcThreadAttrFn)(LPPROC_THREAD_ATTRIBUTE_LIST, | 322 typedef BOOL(WINAPI* UpdateProcThreadAttrFn)(LPPROC_THREAD_ATTRIBUTE_LIST, |
| 332 DWORD, | 323 DWORD, |
| 333 DWORD_PTR, | 324 DWORD_PTR, |
| 334 PVOID, | 325 PVOID, |
| 335 SIZE_T, | 326 SIZE_T, |
| 336 PVOID, | 327 PVOID, |
| 337 PSIZE_T); | 328 PSIZE_T); |
| 338 | 329 |
| 339 typedef VOID(WINAPI* DeleteProcThreadAttrListFn)(LPPROC_THREAD_ATTRIBUTE_LIST); | 330 typedef VOID(WINAPI* DeleteProcThreadAttrListFn)(LPPROC_THREAD_ATTRIBUTE_LIST); |
| 340 | 331 |
| 341 | |
| 342 static InitProcThreadAttrListFn init_proc_thread_attr_list = NULL; | 332 static InitProcThreadAttrListFn init_proc_thread_attr_list = NULL; |
| 343 static UpdateProcThreadAttrFn update_proc_thread_attr = NULL; | 333 static UpdateProcThreadAttrFn update_proc_thread_attr = NULL; |
| 344 static DeleteProcThreadAttrListFn delete_proc_thread_attr_list = NULL; | 334 static DeleteProcThreadAttrListFn delete_proc_thread_attr_list = NULL; |
| 345 | 335 |
| 346 | |
| 347 static bool EnsureInitialized() { | 336 static bool EnsureInitialized() { |
| 348 static bool load_attempted = false; | 337 static bool load_attempted = false; |
| 349 static Mutex* mutex = new Mutex(); | 338 static Mutex* mutex = new Mutex(); |
| 350 HMODULE kernel32_module = GetModuleHandleW(L"kernel32.dll"); | 339 HMODULE kernel32_module = GetModuleHandleW(L"kernel32.dll"); |
| 351 if (!load_attempted) { | 340 if (!load_attempted) { |
| 352 MutexLocker locker(mutex); | 341 MutexLocker locker(mutex); |
| 353 if (load_attempted) { | 342 if (load_attempted) { |
| 354 return (delete_proc_thread_attr_list != NULL); | 343 return (delete_proc_thread_attr_list != NULL); |
| 355 } | 344 } |
| 356 init_proc_thread_attr_list = reinterpret_cast<InitProcThreadAttrListFn>( | 345 init_proc_thread_attr_list = reinterpret_cast<InitProcThreadAttrListFn>( |
| 357 GetProcAddress(kernel32_module, "InitializeProcThreadAttributeList")); | 346 GetProcAddress(kernel32_module, "InitializeProcThreadAttributeList")); |
| 358 update_proc_thread_attr = reinterpret_cast<UpdateProcThreadAttrFn>( | 347 update_proc_thread_attr = reinterpret_cast<UpdateProcThreadAttrFn>( |
| 359 GetProcAddress(kernel32_module, "UpdateProcThreadAttribute")); | 348 GetProcAddress(kernel32_module, "UpdateProcThreadAttribute")); |
| 360 delete_proc_thread_attr_list = reinterpret_cast<DeleteProcThreadAttrListFn>( | 349 delete_proc_thread_attr_list = reinterpret_cast<DeleteProcThreadAttrListFn>( |
| 361 GetProcAddress(kernel32_module, "DeleteProcThreadAttributeList")); | 350 GetProcAddress(kernel32_module, "DeleteProcThreadAttributeList")); |
| 362 load_attempted = true; | 351 load_attempted = true; |
| 363 return (delete_proc_thread_attr_list != NULL); | 352 return (delete_proc_thread_attr_list != NULL); |
| 364 } | 353 } |
| 365 return (delete_proc_thread_attr_list != NULL); | 354 return (delete_proc_thread_attr_list != NULL); |
| 366 } | 355 } |
| 367 | 356 |
| 368 | |
| 369 const int kMaxPipeNameSize = 80; | 357 const int kMaxPipeNameSize = 80; |
| 370 template <int Count> | 358 template <int Count> |
| 371 static int GenerateNames(wchar_t pipe_names[Count][kMaxPipeNameSize]) { | 359 static int GenerateNames(wchar_t pipe_names[Count][kMaxPipeNameSize]) { |
| 372 UUID uuid; | 360 UUID uuid; |
| 373 RPC_STATUS status = UuidCreateSequential(&uuid); | 361 RPC_STATUS status = UuidCreateSequential(&uuid); |
| 374 if ((status != RPC_S_OK) && (status != RPC_S_UUID_LOCAL_ONLY)) { | 362 if ((status != RPC_S_OK) && (status != RPC_S_UUID_LOCAL_ONLY)) { |
| 375 return status; | 363 return status; |
| 376 } | 364 } |
| 377 RPC_WSTR uuid_string; | 365 RPC_WSTR uuid_string; |
| 378 status = UuidToStringW(&uuid, &uuid_string); | 366 status = UuidToStringW(&uuid, &uuid_string); |
| 379 if (status != RPC_S_OK) { | 367 if (status != RPC_S_OK) { |
| 380 return status; | 368 return status; |
| 381 } | 369 } |
| 382 for (int i = 0; i < Count; i++) { | 370 for (int i = 0; i < Count; i++) { |
| 383 static const wchar_t* prefix = L"\\\\.\\Pipe\\dart"; | 371 static const wchar_t* prefix = L"\\\\.\\Pipe\\dart"; |
| 384 _snwprintf(pipe_names[i], kMaxPipeNameSize, L"%s_%s_%d", prefix, | 372 _snwprintf(pipe_names[i], kMaxPipeNameSize, L"%s_%s_%d", prefix, |
| 385 uuid_string, i + 1); | 373 uuid_string, i + 1); |
| 386 } | 374 } |
| 387 status = RpcStringFreeW(&uuid_string); | 375 status = RpcStringFreeW(&uuid_string); |
| 388 if (status != RPC_S_OK) { | 376 if (status != RPC_S_OK) { |
| 389 return status; | 377 return status; |
| 390 } | 378 } |
| 391 return 0; | 379 return 0; |
| 392 } | 380 } |
| 393 | 381 |
| 394 | |
| 395 class ProcessStarter { | 382 class ProcessStarter { |
| 396 public: | 383 public: |
| 397 ProcessStarter(const char* path, | 384 ProcessStarter(const char* path, |
| 398 char* arguments[], | 385 char* arguments[], |
| 399 intptr_t arguments_length, | 386 intptr_t arguments_length, |
| 400 const char* working_directory, | 387 const char* working_directory, |
| 401 char* environment[], | 388 char* environment[], |
| 402 intptr_t environment_length, | 389 intptr_t environment_length, |
| 403 ProcessStartMode mode, | 390 ProcessStartMode mode, |
| 404 intptr_t* in, | 391 intptr_t* in, |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 | 482 |
| 496 system_working_directory_ = NULL; | 483 system_working_directory_ = NULL; |
| 497 if (working_directory_ != NULL) { | 484 if (working_directory_ != NULL) { |
| 498 system_working_directory_ = | 485 system_working_directory_ = |
| 499 StringUtilsWin::Utf8ToWide(working_directory_); | 486 StringUtilsWin::Utf8ToWide(working_directory_); |
| 500 } | 487 } |
| 501 | 488 |
| 502 attribute_list_ = NULL; | 489 attribute_list_ = NULL; |
| 503 } | 490 } |
| 504 | 491 |
| 505 | |
| 506 ~ProcessStarter() { | 492 ~ProcessStarter() { |
| 507 if (attribute_list_ != NULL) { | 493 if (attribute_list_ != NULL) { |
| 508 delete_proc_thread_attr_list(attribute_list_); | 494 delete_proc_thread_attr_list(attribute_list_); |
| 509 } | 495 } |
| 510 } | 496 } |
| 511 | 497 |
| 512 | |
| 513 int Start() { | 498 int Start() { |
| 514 // Create pipes required. | 499 // Create pipes required. |
| 515 int err = CreatePipes(); | 500 int err = CreatePipes(); |
| 516 if (err != 0) { | 501 if (err != 0) { |
| 517 return err; | 502 return err; |
| 518 } | 503 } |
| 519 | 504 |
| 520 // Setup info structures. | 505 // Setup info structures. |
| 521 STARTUPINFOEXW startup_info; | 506 STARTUPINFOEXW startup_info; |
| 522 ZeroMemory(&startup_info, sizeof(startup_info)); | 507 ZeroMemory(&startup_info, sizeof(startup_info)); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 } | 585 } |
| 601 } | 586 } |
| 602 | 587 |
| 603 CloseHandle(process_info.hThread); | 588 CloseHandle(process_info.hThread); |
| 604 | 589 |
| 605 // Return process id. | 590 // Return process id. |
| 606 *id_ = process_info.dwProcessId; | 591 *id_ = process_info.dwProcessId; |
| 607 return 0; | 592 return 0; |
| 608 } | 593 } |
| 609 | 594 |
| 610 | |
| 611 int CreatePipes() { | 595 int CreatePipes() { |
| 612 // Generate unique pipe names for the four named pipes needed. | 596 // Generate unique pipe names for the four named pipes needed. |
| 613 wchar_t pipe_names[4][kMaxPipeNameSize]; | 597 wchar_t pipe_names[4][kMaxPipeNameSize]; |
| 614 int status = GenerateNames<4>(pipe_names); | 598 int status = GenerateNames<4>(pipe_names); |
| 615 if (status != 0) { | 599 if (status != 0) { |
| 616 SetOsErrorMessage(os_error_message_); | 600 SetOsErrorMessage(os_error_message_); |
| 617 Log::PrintErr("UuidCreateSequential failed %d\n", status); | 601 Log::PrintErr("UuidCreateSequential failed %d\n", status); |
| 618 return status; | 602 return status; |
| 619 } | 603 } |
| 620 | 604 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 645 } | 629 } |
| 646 | 630 |
| 647 stderr_handles_[kWriteHandle] = OpenNul(); | 631 stderr_handles_[kWriteHandle] = OpenNul(); |
| 648 if (stderr_handles_[kWriteHandle] == INVALID_HANDLE_VALUE) { | 632 if (stderr_handles_[kWriteHandle] == INVALID_HANDLE_VALUE) { |
| 649 return CleanupAndReturnError(); | 633 return CleanupAndReturnError(); |
| 650 } | 634 } |
| 651 } | 635 } |
| 652 return 0; | 636 return 0; |
| 653 } | 637 } |
| 654 | 638 |
| 655 | |
| 656 int CleanupAndReturnError() { | 639 int CleanupAndReturnError() { |
| 657 int error_code = SetOsErrorMessage(os_error_message_); | 640 int error_code = SetOsErrorMessage(os_error_message_); |
| 658 CloseProcessPipes(stdin_handles_, stdout_handles_, stderr_handles_, | 641 CloseProcessPipes(stdin_handles_, stdout_handles_, stderr_handles_, |
| 659 exit_handles_); | 642 exit_handles_); |
| 660 return error_code; | 643 return error_code; |
| 661 } | 644 } |
| 662 | 645 |
| 663 | |
| 664 HANDLE stdin_handles_[2]; | 646 HANDLE stdin_handles_[2]; |
| 665 HANDLE stdout_handles_[2]; | 647 HANDLE stdout_handles_[2]; |
| 666 HANDLE stderr_handles_[2]; | 648 HANDLE stderr_handles_[2]; |
| 667 HANDLE exit_handles_[2]; | 649 HANDLE exit_handles_[2]; |
| 668 | 650 |
| 669 const wchar_t* system_working_directory_; | 651 const wchar_t* system_working_directory_; |
| 670 wchar_t* command_line_; | 652 wchar_t* command_line_; |
| 671 wchar_t* environment_block_; | 653 wchar_t* environment_block_; |
| 672 LPPROC_THREAD_ATTRIBUTE_LIST attribute_list_; | 654 LPPROC_THREAD_ATTRIBUTE_LIST attribute_list_; |
| 673 | 655 |
| 674 const char* path_; | 656 const char* path_; |
| 675 const char* working_directory_; | 657 const char* working_directory_; |
| 676 ProcessStartMode mode_; | 658 ProcessStartMode mode_; |
| 677 intptr_t* in_; | 659 intptr_t* in_; |
| 678 intptr_t* out_; | 660 intptr_t* out_; |
| 679 intptr_t* err_; | 661 intptr_t* err_; |
| 680 intptr_t* id_; | 662 intptr_t* id_; |
| 681 intptr_t* exit_handler_; | 663 intptr_t* exit_handler_; |
| 682 char** os_error_message_; | 664 char** os_error_message_; |
| 683 | 665 |
| 684 private: | 666 private: |
| 685 DISALLOW_ALLOCATION(); | 667 DISALLOW_ALLOCATION(); |
| 686 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter); | 668 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter); |
| 687 }; | 669 }; |
| 688 | 670 |
| 689 | |
| 690 int Process::Start(const char* path, | 671 int Process::Start(const char* path, |
| 691 char* arguments[], | 672 char* arguments[], |
| 692 intptr_t arguments_length, | 673 intptr_t arguments_length, |
| 693 const char* working_directory, | 674 const char* working_directory, |
| 694 char* environment[], | 675 char* environment[], |
| 695 intptr_t environment_length, | 676 intptr_t environment_length, |
| 696 ProcessStartMode mode, | 677 ProcessStartMode mode, |
| 697 intptr_t* in, | 678 intptr_t* in, |
| 698 intptr_t* out, | 679 intptr_t* out, |
| 699 intptr_t* err, | 680 intptr_t* err, |
| 700 intptr_t* id, | 681 intptr_t* id, |
| 701 intptr_t* exit_handler, | 682 intptr_t* exit_handler, |
| 702 char** os_error_message) { | 683 char** os_error_message) { |
| 703 ProcessStarter starter(path, arguments, arguments_length, working_directory, | 684 ProcessStarter starter(path, arguments, arguments_length, working_directory, |
| 704 environment, environment_length, mode, in, out, err, | 685 environment, environment_length, mode, in, out, err, |
| 705 id, exit_handler, os_error_message); | 686 id, exit_handler, os_error_message); |
| 706 return starter.Start(); | 687 return starter.Start(); |
| 707 } | 688 } |
| 708 | 689 |
| 709 | |
| 710 class BufferList : public BufferListBase { | 690 class BufferList : public BufferListBase { |
| 711 public: | 691 public: |
| 712 BufferList() : read_pending_(true) {} | 692 BufferList() : read_pending_(true) {} |
| 713 | 693 |
| 714 // Indicate that data has been read into the buffer provided to | 694 // Indicate that data has been read into the buffer provided to |
| 715 // overlapped read. | 695 // overlapped read. |
| 716 void DataIsRead(intptr_t size) { | 696 void DataIsRead(intptr_t size) { |
| 717 ASSERT(read_pending_ == true); | 697 ASSERT(read_pending_ == true); |
| 718 set_data_size(data_size() + size); | 698 set_data_size(data_size() + size); |
| 719 set_free_size(free_size() - size); | 699 set_free_size(free_size() - size); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 747 } | 727 } |
| 748 | 728 |
| 749 void FreeDataBuffer() { Free(); } | 729 void FreeDataBuffer() { Free(); } |
| 750 | 730 |
| 751 private: | 731 private: |
| 752 bool read_pending_; | 732 bool read_pending_; |
| 753 | 733 |
| 754 DISALLOW_COPY_AND_ASSIGN(BufferList); | 734 DISALLOW_COPY_AND_ASSIGN(BufferList); |
| 755 }; | 735 }; |
| 756 | 736 |
| 757 | |
| 758 class OverlappedHandle { | 737 class OverlappedHandle { |
| 759 public: | 738 public: |
| 760 OverlappedHandle() {} | 739 OverlappedHandle() {} |
| 761 | 740 |
| 762 void Init(HANDLE handle, HANDLE event) { | 741 void Init(HANDLE handle, HANDLE event) { |
| 763 handle_ = handle; | 742 handle_ = handle; |
| 764 event_ = event; | 743 event_ = event; |
| 765 ClearOverlapped(); | 744 ClearOverlapped(); |
| 766 } | 745 } |
| 767 | 746 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 818 | 797 |
| 819 OVERLAPPED overlapped_; | 798 OVERLAPPED overlapped_; |
| 820 HANDLE handle_; | 799 HANDLE handle_; |
| 821 HANDLE event_; | 800 HANDLE event_; |
| 822 BufferList buffer_; | 801 BufferList buffer_; |
| 823 | 802 |
| 824 DISALLOW_ALLOCATION(); | 803 DISALLOW_ALLOCATION(); |
| 825 DISALLOW_COPY_AND_ASSIGN(OverlappedHandle); | 804 DISALLOW_COPY_AND_ASSIGN(OverlappedHandle); |
| 826 }; | 805 }; |
| 827 | 806 |
| 828 | |
| 829 bool Process::Wait(intptr_t pid, | 807 bool Process::Wait(intptr_t pid, |
| 830 intptr_t in, | 808 intptr_t in, |
| 831 intptr_t out, | 809 intptr_t out, |
| 832 intptr_t err, | 810 intptr_t err, |
| 833 intptr_t exit_event, | 811 intptr_t exit_event, |
| 834 ProcessResult* result) { | 812 ProcessResult* result) { |
| 835 // Close input to the process right away. | 813 // Close input to the process right away. |
| 836 reinterpret_cast<FileHandle*>(in)->Close(); | 814 reinterpret_cast<FileHandle*>(in)->Close(); |
| 837 | 815 |
| 838 // All pipes created to the sub-process support overlapped IO. | 816 // All pipes created to the sub-process support overlapped IO. |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 902 oh[2].FreeDataBuffer(); | 880 oh[2].FreeDataBuffer(); |
| 903 intptr_t exit_code = exit_codes[0]; | 881 intptr_t exit_code = exit_codes[0]; |
| 904 intptr_t negative = exit_codes[1]; | 882 intptr_t negative = exit_codes[1]; |
| 905 if (negative != 0) { | 883 if (negative != 0) { |
| 906 exit_code = -exit_code; | 884 exit_code = -exit_code; |
| 907 } | 885 } |
| 908 result->set_exit_code(exit_code); | 886 result->set_exit_code(exit_code); |
| 909 return true; | 887 return true; |
| 910 } | 888 } |
| 911 | 889 |
| 912 | |
| 913 bool Process::Kill(intptr_t id, int signal) { | 890 bool Process::Kill(intptr_t id, int signal) { |
| 914 USE(signal); // signal is not used on Windows. | 891 USE(signal); // signal is not used on Windows. |
| 915 HANDLE process_handle; | 892 HANDLE process_handle; |
| 916 HANDLE wait_handle; | 893 HANDLE wait_handle; |
| 917 HANDLE exit_pipe; | 894 HANDLE exit_pipe; |
| 918 // First check the process info list for the process to get a handle to it. | 895 // First check the process info list for the process to get a handle to it. |
| 919 bool success = ProcessInfoList::LookupProcess(id, &process_handle, | 896 bool success = ProcessInfoList::LookupProcess(id, &process_handle, |
| 920 &wait_handle, &exit_pipe); | 897 &wait_handle, &exit_pipe); |
| 921 // For detached processes we don't have the process registered in the | 898 // For detached processes we don't have the process registered in the |
| 922 // process info list. Try to look it up through the OS. | 899 // process info list. Try to look it up through the OS. |
| 923 if (!success) { | 900 if (!success) { |
| 924 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, id); | 901 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, id); |
| 925 // The process is already dead. | 902 // The process is already dead. |
| 926 if (process_handle == INVALID_HANDLE_VALUE) { | 903 if (process_handle == INVALID_HANDLE_VALUE) { |
| 927 return false; | 904 return false; |
| 928 } | 905 } |
| 929 } | 906 } |
| 930 BOOL result = TerminateProcess(process_handle, -1); | 907 BOOL result = TerminateProcess(process_handle, -1); |
| 931 return result ? true : false; | 908 return result ? true : false; |
| 932 } | 909 } |
| 933 | 910 |
| 934 | |
| 935 void Process::TerminateExitCodeHandler() { | 911 void Process::TerminateExitCodeHandler() { |
| 936 // Nothing needs to be done on Windows. | 912 // Nothing needs to be done on Windows. |
| 937 } | 913 } |
| 938 | 914 |
| 939 | |
| 940 intptr_t Process::CurrentProcessId() { | 915 intptr_t Process::CurrentProcessId() { |
| 941 return static_cast<intptr_t>(GetCurrentProcessId()); | 916 return static_cast<intptr_t>(GetCurrentProcessId()); |
| 942 } | 917 } |
| 943 | 918 |
| 944 | |
| 945 int64_t Process::CurrentRSS() { | 919 int64_t Process::CurrentRSS() { |
| 946 PROCESS_MEMORY_COUNTERS pmc; | 920 PROCESS_MEMORY_COUNTERS pmc; |
| 947 if (!GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) { | 921 if (!GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) { |
| 948 return -1; | 922 return -1; |
| 949 } | 923 } |
| 950 return pmc.WorkingSetSize; | 924 return pmc.WorkingSetSize; |
| 951 } | 925 } |
| 952 | 926 |
| 953 | |
| 954 int64_t Process::MaxRSS() { | 927 int64_t Process::MaxRSS() { |
| 955 PROCESS_MEMORY_COUNTERS pmc; | 928 PROCESS_MEMORY_COUNTERS pmc; |
| 956 if (!GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) { | 929 if (!GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) { |
| 957 return -1; | 930 return -1; |
| 958 } | 931 } |
| 959 return pmc.PeakWorkingSetSize; | 932 return pmc.PeakWorkingSetSize; |
| 960 } | 933 } |
| 961 | 934 |
| 962 | |
| 963 static SignalInfo* signal_handlers = NULL; | 935 static SignalInfo* signal_handlers = NULL; |
| 964 static Mutex* signal_mutex = new Mutex(); | 936 static Mutex* signal_mutex = new Mutex(); |
| 965 | 937 |
| 966 | |
| 967 SignalInfo::~SignalInfo() { | 938 SignalInfo::~SignalInfo() { |
| 968 FileHandle* file_handle = reinterpret_cast<FileHandle*>(fd_); | 939 FileHandle* file_handle = reinterpret_cast<FileHandle*>(fd_); |
| 969 file_handle->Close(); | 940 file_handle->Close(); |
| 970 file_handle->Release(); | 941 file_handle->Release(); |
| 971 } | 942 } |
| 972 | 943 |
| 973 | |
| 974 BOOL WINAPI SignalHandler(DWORD signal) { | 944 BOOL WINAPI SignalHandler(DWORD signal) { |
| 975 MutexLocker lock(signal_mutex); | 945 MutexLocker lock(signal_mutex); |
| 976 const SignalInfo* handler = signal_handlers; | 946 const SignalInfo* handler = signal_handlers; |
| 977 bool handled = false; | 947 bool handled = false; |
| 978 while (handler != NULL) { | 948 while (handler != NULL) { |
| 979 if (handler->signal() == signal) { | 949 if (handler->signal() == signal) { |
| 980 int value = 0; | 950 int value = 0; |
| 981 SocketBase::Write(handler->fd(), &value, 1, SocketBase::kAsync); | 951 SocketBase::Write(handler->fd(), &value, 1, SocketBase::kAsync); |
| 982 handled = true; | 952 handled = true; |
| 983 } | 953 } |
| 984 handler = handler->next(); | 954 handler = handler->next(); |
| 985 } | 955 } |
| 986 return handled; | 956 return handled; |
| 987 } | 957 } |
| 988 | 958 |
| 989 | |
| 990 intptr_t GetWinSignal(intptr_t signal) { | 959 intptr_t GetWinSignal(intptr_t signal) { |
| 991 switch (signal) { | 960 switch (signal) { |
| 992 case kSighup: | 961 case kSighup: |
| 993 return CTRL_CLOSE_EVENT; | 962 return CTRL_CLOSE_EVENT; |
| 994 case kSigint: | 963 case kSigint: |
| 995 return CTRL_C_EVENT; | 964 return CTRL_C_EVENT; |
| 996 default: | 965 default: |
| 997 return -1; | 966 return -1; |
| 998 } | 967 } |
| 999 } | 968 } |
| 1000 | 969 |
| 1001 | |
| 1002 intptr_t Process::SetSignalHandler(intptr_t signal) { | 970 intptr_t Process::SetSignalHandler(intptr_t signal) { |
| 1003 signal = GetWinSignal(signal); | 971 signal = GetWinSignal(signal); |
| 1004 if (signal == -1) { | 972 if (signal == -1) { |
| 1005 SetLastError(ERROR_NOT_SUPPORTED); | 973 SetLastError(ERROR_NOT_SUPPORTED); |
| 1006 return -1; | 974 return -1; |
| 1007 } | 975 } |
| 1008 | 976 |
| 1009 // Generate a unique pipe name for the named pipe. | 977 // Generate a unique pipe name for the named pipe. |
| 1010 wchar_t pipe_name[kMaxPipeNameSize]; | 978 wchar_t pipe_name[kMaxPipeNameSize]; |
| 1011 int status = GenerateNames<1>(&pipe_name); | 979 int status = GenerateNames<1>(&pipe_name); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1035 write_handle->Release(); | 1003 write_handle->Release(); |
| 1036 CloseProcessPipe(fds); | 1004 CloseProcessPipe(fds); |
| 1037 SetLastError(error_code); | 1005 SetLastError(error_code); |
| 1038 return -1; | 1006 return -1; |
| 1039 } | 1007 } |
| 1040 } | 1008 } |
| 1041 signal_handlers = new SignalInfo(write_fd, signal, signal_handlers); | 1009 signal_handlers = new SignalInfo(write_fd, signal, signal_handlers); |
| 1042 return reinterpret_cast<intptr_t>(new FileHandle(fds[kReadHandle])); | 1010 return reinterpret_cast<intptr_t>(new FileHandle(fds[kReadHandle])); |
| 1043 } | 1011 } |
| 1044 | 1012 |
| 1045 | |
| 1046 void Process::ClearSignalHandler(intptr_t signal, Dart_Port port) { | 1013 void Process::ClearSignalHandler(intptr_t signal, Dart_Port port) { |
| 1047 signal = GetWinSignal(signal); | 1014 signal = GetWinSignal(signal); |
| 1048 if (signal == -1) { | 1015 if (signal == -1) { |
| 1049 return; | 1016 return; |
| 1050 } | 1017 } |
| 1051 MutexLocker lock(signal_mutex); | 1018 MutexLocker lock(signal_mutex); |
| 1052 SignalInfo* handler = signal_handlers; | 1019 SignalInfo* handler = signal_handlers; |
| 1053 while (handler != NULL) { | 1020 while (handler != NULL) { |
| 1054 bool remove = false; | 1021 bool remove = false; |
| 1055 if (handler->signal() == signal) { | 1022 if (handler->signal() == signal) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1073 USE(SetConsoleCtrlHandler(SignalHandler, false)); | 1040 USE(SetConsoleCtrlHandler(SignalHandler, false)); |
| 1074 } | 1041 } |
| 1075 } | 1042 } |
| 1076 | 1043 |
| 1077 } // namespace bin | 1044 } // namespace bin |
| 1078 } // namespace dart | 1045 } // namespace dart |
| 1079 | 1046 |
| 1080 #endif // defined(HOST_OS_WINDOWS) | 1047 #endif // defined(HOST_OS_WINDOWS) |
| 1081 | 1048 |
| 1082 #endif // !defined(DART_IO_DISABLED) | 1049 #endif // !defined(DART_IO_DISABLED) |
| OLD | NEW |