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 |