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 "platform/globals.h" | 5 #include "platform/globals.h" |
6 #if defined(TARGET_OS_WINDOWS) | 6 #if defined(TARGET_OS_WINDOWS) |
7 | 7 |
8 #include "bin/process.h" | |
9 | |
8 #include <process.h> // NOLINT | 10 #include <process.h> // NOLINT |
9 | 11 |
10 #include "bin/builtin.h" | 12 #include "bin/builtin.h" |
11 #include "bin/dartutils.h" | 13 #include "bin/dartutils.h" |
12 #include "bin/process.h" | |
13 #include "bin/eventhandler.h" | 14 #include "bin/eventhandler.h" |
14 #include "bin/lockers.h" | 15 #include "bin/lockers.h" |
15 #include "bin/log.h" | 16 #include "bin/log.h" |
16 #include "bin/socket.h" | 17 #include "bin/socket.h" |
17 #include "bin/thread.h" | 18 #include "bin/thread.h" |
18 #include "bin/utils.h" | 19 #include "bin/utils.h" |
19 #include "bin/utils_win.h" | 20 #include "bin/utils_win.h" |
20 | 21 |
21 | |
22 namespace dart { | 22 namespace dart { |
23 namespace bin { | 23 namespace bin { |
24 | 24 |
25 static const int kReadHandle = 0; | 25 static const int kReadHandle = 0; |
26 static const int kWriteHandle = 1; | 26 static const int kWriteHandle = 1; |
27 | 27 |
28 | 28 |
29 // ProcessInfo is used to map a process id to the process handle, | 29 // ProcessInfo is used to map a process id to the process handle, |
30 // wait handle for registered exit code event and the pipe used to | 30 // wait handle for registered exit code event and the pipe used to |
31 // communicate the exit code of the process to Dart. | 31 // communicate the exit code of the process to Dart. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
65 DWORD process_id_; | 65 DWORD process_id_; |
66 // Process handle. | 66 // Process handle. |
67 HANDLE process_handle_; | 67 HANDLE process_handle_; |
68 // Wait handle identifying the exit-code wait operation registered | 68 // Wait handle identifying the exit-code wait operation registered |
69 // with RegisterWaitForSingleObject. | 69 // with RegisterWaitForSingleObject. |
70 HANDLE wait_handle_; | 70 HANDLE wait_handle_; |
71 // File descriptor for pipe to report exit code. | 71 // File descriptor for pipe to report exit code. |
72 HANDLE exit_pipe_; | 72 HANDLE exit_pipe_; |
73 // Link to next ProcessInfo object in the singly-linked list. | 73 // Link to next ProcessInfo object in the singly-linked list. |
74 ProcessInfo* next_; | 74 ProcessInfo* next_; |
75 | |
76 DISALLOW_COPY_AND_ASSIGN(ProcessInfo); | |
75 }; | 77 }; |
76 | 78 |
77 | 79 |
78 // Singly-linked list of ProcessInfo objects for all active processes | 80 // Singly-linked list of ProcessInfo objects for all active processes |
79 // started from Dart. | 81 // started from Dart. |
80 class ProcessInfoList { | 82 class ProcessInfoList { |
81 public: | 83 public: |
82 static void AddProcess(DWORD pid, HANDLE handle, HANDLE pipe) { | 84 static void AddProcess(DWORD pid, HANDLE handle, HANDLE pipe) { |
83 // Register a callback to extract the exit code, when the process | 85 // Register a callback to extract the exit code, when the process |
84 // is signaled. The callback runs in a independent thread from the OS pool. | 86 // is signaled. The callback runs in a independent thread from the OS pool. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
136 } | 138 } |
137 prev = current; | 139 prev = current; |
138 current = current->next(); | 140 current = current->next(); |
139 } | 141 } |
140 } | 142 } |
141 | 143 |
142 private: | 144 private: |
143 // Callback called when an exit code is available from one of the | 145 // Callback called when an exit code is available from one of the |
144 // processes in the list. | 146 // processes in the list. |
145 static void CALLBACK ExitCodeCallback(PVOID data, BOOLEAN timed_out) { | 147 static void CALLBACK ExitCodeCallback(PVOID data, BOOLEAN timed_out) { |
146 if (timed_out) return; | 148 if (timed_out) { |
149 return; | |
150 } | |
147 DWORD pid = reinterpret_cast<DWORD>(data); | 151 DWORD pid = reinterpret_cast<DWORD>(data); |
148 HANDLE handle; | 152 HANDLE handle; |
149 HANDLE wait_handle; | 153 HANDLE wait_handle; |
150 HANDLE exit_pipe; | 154 HANDLE exit_pipe; |
151 bool success = LookupProcess(pid, &handle, &wait_handle, &exit_pipe); | 155 bool success = LookupProcess(pid, &handle, &wait_handle, &exit_pipe); |
152 if (!success) { | 156 if (!success) { |
153 FATAL("Failed to lookup process in list of active processes"); | 157 FATAL("Failed to lookup process in list of active processes"); |
154 } | 158 } |
155 // Unregister the event in a non-blocking way. | 159 // Unregister the event in a non-blocking way. |
156 BOOL ok = UnregisterWait(wait_handle); | 160 BOOL ok = UnregisterWait(wait_handle); |
157 if (!ok && GetLastError() != ERROR_IO_PENDING) { | 161 if (!ok && (GetLastError() != ERROR_IO_PENDING)) { |
158 FATAL("Failed unregistering wait operation"); | 162 FATAL("Failed unregistering wait operation"); |
159 } | 163 } |
160 // Get and report the exit code to Dart. | 164 // Get and report the exit code to Dart. |
161 int exit_code; | 165 int exit_code; |
162 ok = GetExitCodeProcess(handle, | 166 ok = GetExitCodeProcess(handle, reinterpret_cast<DWORD*>(&exit_code)); |
163 reinterpret_cast<DWORD*>(&exit_code)); | |
164 if (!ok) { | 167 if (!ok) { |
165 FATAL1("GetExitCodeProcess failed %d\n", GetLastError()); | 168 FATAL1("GetExitCodeProcess failed %d\n", GetLastError()); |
166 } | 169 } |
167 int negative = 0; | 170 int negative = 0; |
168 if (exit_code < 0) { | 171 if (exit_code < 0) { |
169 exit_code = abs(exit_code); | 172 exit_code = abs(exit_code); |
170 negative = 1; | 173 negative = 1; |
171 } | 174 } |
172 int message[2] = { exit_code, negative }; | 175 int message[2] = { exit_code, negative }; |
173 DWORD written; | 176 DWORD written; |
174 ok = WriteFile(exit_pipe, message, sizeof(message), &written, NULL); | 177 ok = WriteFile(exit_pipe, message, sizeof(message), &written, NULL); |
175 // If the process has been closed, the read end of the exit | 178 // If the process has been closed, the read end of the exit |
176 // pipe has been closed. It is therefore not a problem that | 179 // pipe has been closed. It is therefore not a problem that |
177 // WriteFile fails with a closed pipe error | 180 // WriteFile fails with a closed pipe error |
178 // (ERROR_NO_DATA). Other errors should not happen. | 181 // (ERROR_NO_DATA). Other errors should not happen. |
179 if (ok && written != sizeof(message)) { | 182 if (ok && (written != sizeof(message))) { |
180 FATAL("Failed to write entire process exit message"); | 183 FATAL("Failed to write entire process exit message"); |
181 } else if (!ok && GetLastError() != ERROR_NO_DATA) { | 184 } else if (!ok && (GetLastError() != ERROR_NO_DATA)) { |
182 FATAL1("Failed to write exit code: %d", GetLastError()); | 185 FATAL1("Failed to write exit code: %d", GetLastError()); |
183 } | 186 } |
184 // Remove the process from the list of active processes. | 187 // Remove the process from the list of active processes. |
185 RemoveProcess(pid); | 188 RemoveProcess(pid); |
186 } | 189 } |
187 | 190 |
188 // Linked list of ProcessInfo objects for all active processes | 191 // Linked list of ProcessInfo objects for all active processes |
189 // started from Dart code. | 192 // started from Dart code. |
190 static ProcessInfo* active_processes_; | 193 static ProcessInfo* active_processes_; |
191 // Mutex protecting all accesses to the linked list of active | 194 // Mutex protecting all accesses to the linked list of active |
192 // processes. | 195 // processes. |
193 static Mutex* mutex_; | 196 static Mutex* mutex_; |
197 | |
198 DISALLOW_ALLOCATION(); | |
199 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList); | |
194 }; | 200 }; |
195 | 201 |
196 | 202 |
197 ProcessInfo* ProcessInfoList::active_processes_ = NULL; | 203 ProcessInfo* ProcessInfoList::active_processes_ = NULL; |
198 Mutex* ProcessInfoList::mutex_ = new Mutex(); | 204 Mutex* ProcessInfoList::mutex_ = new Mutex(); |
199 | 205 |
200 | 206 |
201 // Types of pipes to create. | 207 // Types of pipes to create. |
202 enum NamedPipeType { | 208 enum NamedPipeType { |
203 kInheritRead, | 209 kInheritRead, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
242 0, | 248 0, |
243 &inherit_handle, | 249 &inherit_handle, |
244 OPEN_EXISTING, | 250 OPEN_EXISTING, |
245 FILE_READ_ATTRIBUTES | FILE_FLAG_OVERLAPPED, | 251 FILE_READ_ATTRIBUTES | FILE_FLAG_OVERLAPPED, |
246 NULL); | 252 NULL); |
247 if (handles[kReadHandle] == INVALID_HANDLE_VALUE) { | 253 if (handles[kReadHandle] == INVALID_HANDLE_VALUE) { |
248 Log::PrintErr("CreateFile failed %d\n", GetLastError()); | 254 Log::PrintErr("CreateFile failed %d\n", GetLastError()); |
249 return false; | 255 return false; |
250 } | 256 } |
251 } else { | 257 } else { |
252 ASSERT(type == kInheritWrite || type == kInheritNone); | 258 ASSERT((type == kInheritWrite) || (type == kInheritNone)); |
253 handles[kReadHandle] = | 259 handles[kReadHandle] = |
254 CreateNamedPipeW(pipe_name, | 260 CreateNamedPipeW(pipe_name, |
255 PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, | 261 PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, |
256 PIPE_TYPE_BYTE | PIPE_WAIT, | 262 PIPE_TYPE_BYTE | PIPE_WAIT, |
257 1, // Number of pipes | 263 1, // Number of pipes |
258 1024, // Out buffer size | 264 1024, // Out buffer size |
259 1024, // In buffer size | 265 1024, // In buffer size |
260 0, // Timeout in ms | 266 0, // Timeout in ms |
261 NULL); | 267 NULL); |
262 | 268 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
350 static UpdateProcThreadAttrFn update_proc_thread_attr = NULL; | 356 static UpdateProcThreadAttrFn update_proc_thread_attr = NULL; |
351 static DeleteProcThreadAttrListFn delete_proc_thread_attr_list = NULL; | 357 static DeleteProcThreadAttrListFn delete_proc_thread_attr_list = NULL; |
352 | 358 |
353 | 359 |
354 static bool EnsureInitialized() { | 360 static bool EnsureInitialized() { |
355 static bool load_attempted = false; | 361 static bool load_attempted = false; |
356 static Mutex* mutex = new Mutex(); | 362 static Mutex* mutex = new Mutex(); |
357 HMODULE kernel32_module = GetModuleHandleW(L"kernel32.dll"); | 363 HMODULE kernel32_module = GetModuleHandleW(L"kernel32.dll"); |
358 if (!load_attempted) { | 364 if (!load_attempted) { |
359 MutexLocker locker(mutex); | 365 MutexLocker locker(mutex); |
360 if (load_attempted) return delete_proc_thread_attr_list != NULL; | 366 if (load_attempted) { |
367 return (delete_proc_thread_attr_list != NULL); | |
368 } | |
361 init_proc_thread_attr_list = reinterpret_cast<InitProcThreadAttrListFn>( | 369 init_proc_thread_attr_list = reinterpret_cast<InitProcThreadAttrListFn>( |
362 GetProcAddress(kernel32_module, "InitializeProcThreadAttributeList")); | 370 GetProcAddress(kernel32_module, "InitializeProcThreadAttributeList")); |
363 update_proc_thread_attr = | 371 update_proc_thread_attr = reinterpret_cast<UpdateProcThreadAttrFn>( |
364 reinterpret_cast<UpdateProcThreadAttrFn>( | 372 GetProcAddress(kernel32_module, "UpdateProcThreadAttribute")); |
365 GetProcAddress(kernel32_module, "UpdateProcThreadAttribute")); | |
366 delete_proc_thread_attr_list = reinterpret_cast<DeleteProcThreadAttrListFn>( | 373 delete_proc_thread_attr_list = reinterpret_cast<DeleteProcThreadAttrListFn>( |
367 reinterpret_cast<DeleteProcThreadAttrListFn>( | 374 GetProcAddress(kernel32_module, "DeleteProcThreadAttributeList")); |
368 GetProcAddress(kernel32_module, "DeleteProcThreadAttributeList"))); | |
369 load_attempted = true; | 375 load_attempted = true; |
370 return delete_proc_thread_attr_list != NULL; | 376 return (delete_proc_thread_attr_list != NULL); |
371 } | 377 } |
372 return delete_proc_thread_attr_list != NULL; | 378 return (delete_proc_thread_attr_list != NULL); |
373 } | 379 } |
374 | 380 |
375 | 381 |
376 const int kMaxPipeNameSize = 80; | 382 const int kMaxPipeNameSize = 80; |
377 template<int Count> | 383 template<int Count> |
378 static int GenerateNames(wchar_t pipe_names[Count][kMaxPipeNameSize]) { | 384 static int GenerateNames(wchar_t pipe_names[Count][kMaxPipeNameSize]) { |
379 UUID uuid; | 385 UUID uuid; |
380 RPC_STATUS status = UuidCreateSequential(&uuid); | 386 RPC_STATUS status = UuidCreateSequential(&uuid); |
381 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { | 387 if ((status != RPC_S_OK) && (status != RPC_S_UUID_LOCAL_ONLY)) { |
382 return status; | 388 return status; |
383 } | 389 } |
384 RPC_WSTR uuid_string; | 390 RPC_WSTR uuid_string; |
385 status = UuidToStringW(&uuid, &uuid_string); | 391 status = UuidToStringW(&uuid, &uuid_string); |
386 if (status != RPC_S_OK) { | 392 if (status != RPC_S_OK) { |
387 return status; | 393 return status; |
388 } | 394 } |
389 for (int i = 0; i < Count; i++) { | 395 for (int i = 0; i < Count; i++) { |
390 static const wchar_t* prefix = L"\\\\.\\Pipe\\dart"; | 396 static const wchar_t* prefix = L"\\\\.\\Pipe\\dart"; |
391 _snwprintf(pipe_names[i], | 397 _snwprintf(pipe_names[i], |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
444 | 450 |
445 // Compute command-line length. | 451 // Compute command-line length. |
446 int command_line_length = wcslen(system_path); | 452 int command_line_length = wcslen(system_path); |
447 for (int i = 0; i < arguments_length; i++) { | 453 for (int i = 0; i < arguments_length; i++) { |
448 command_line_length += wcslen(system_arguments[i]); | 454 command_line_length += wcslen(system_arguments[i]); |
449 } | 455 } |
450 // Account for null termination and one space per argument. | 456 // Account for null termination and one space per argument. |
451 command_line_length += arguments_length + 1; | 457 command_line_length += arguments_length + 1; |
452 | 458 |
453 // Put together command-line string. | 459 // Put together command-line string. |
454 command_line_ = new wchar_t[command_line_length]; | 460 command_line_ = reinterpret_cast<wchar_t*>(Dart_ScopeAllocate( |
zra
2016/03/15 18:12:29
Changed to scope allocated.
| |
461 command_line_length * sizeof(*command_line_))); | |
455 int len = 0; | 462 int len = 0; |
456 int remaining = command_line_length; | 463 int remaining = command_line_length; |
457 int written = | 464 int written = |
458 _snwprintf(command_line_ + len, remaining, L"%s", system_path); | 465 _snwprintf(command_line_ + len, remaining, L"%s", system_path); |
459 len += written; | 466 len += written; |
460 remaining -= written; | 467 remaining -= written; |
461 ASSERT(remaining >= 0); | 468 ASSERT(remaining >= 0); |
462 for (int i = 0; i < arguments_length; i++) { | 469 for (int i = 0; i < arguments_length; i++) { |
463 written = | 470 written = _snwprintf( |
464 _snwprintf( | 471 command_line_ + len, remaining, L" %s", system_arguments[i]); |
465 command_line_ + len, remaining, L" %s", system_arguments[i]); | |
466 len += written; | 472 len += written; |
467 remaining -= written; | 473 remaining -= written; |
468 ASSERT(remaining >= 0); | 474 ASSERT(remaining >= 0); |
469 } | 475 } |
470 | 476 |
471 // Create environment block if an environment is supplied. | 477 // Create environment block if an environment is supplied. |
472 environment_block_ = NULL; | 478 environment_block_ = NULL; |
473 if (environment != NULL) { | 479 if (environment != NULL) { |
474 wchar_t** system_environment; | 480 wchar_t** system_environment; |
475 system_environment = reinterpret_cast<wchar_t**>( | 481 system_environment = reinterpret_cast<wchar_t**>( |
476 Dart_ScopeAllocate(environment_length * sizeof(*system_environment))); | 482 Dart_ScopeAllocate(environment_length * sizeof(*system_environment))); |
477 // Convert environment strings to system strings. | 483 // Convert environment strings to system strings. |
478 for (intptr_t i = 0; i < environment_length; i++) { | 484 for (intptr_t i = 0; i < environment_length; i++) { |
479 system_environment[i] = StringUtilsWin::Utf8ToWide(environment[i]); | 485 system_environment[i] = StringUtilsWin::Utf8ToWide(environment[i]); |
480 } | 486 } |
481 | 487 |
482 // An environment block is a sequence of zero-terminated strings | 488 // An environment block is a sequence of zero-terminated strings |
483 // followed by a block-terminating zero char. | 489 // followed by a block-terminating zero char. |
484 intptr_t block_size = 1; | 490 intptr_t block_size = 1; |
485 for (intptr_t i = 0; i < environment_length; i++) { | 491 for (intptr_t i = 0; i < environment_length; i++) { |
486 block_size += wcslen(system_environment[i]) + 1; | 492 block_size += wcslen(system_environment[i]) + 1; |
487 } | 493 } |
488 environment_block_ = new wchar_t[block_size]; | 494 environment_block_ = reinterpret_cast<wchar_t*>(Dart_ScopeAllocate( |
zra
2016/03/15 18:12:29
ditto.
| |
495 block_size * sizeof(*environment_block_))); | |
489 intptr_t block_index = 0; | 496 intptr_t block_index = 0; |
490 for (intptr_t i = 0; i < environment_length; i++) { | 497 for (intptr_t i = 0; i < environment_length; i++) { |
491 intptr_t len = wcslen(system_environment[i]); | 498 intptr_t len = wcslen(system_environment[i]); |
492 intptr_t result = _snwprintf(environment_block_ + block_index, | 499 intptr_t result = _snwprintf(environment_block_ + block_index, |
493 len, | 500 len, |
494 L"%s", | 501 L"%s", |
495 system_environment[i]); | 502 system_environment[i]); |
496 ASSERT(result == len); | 503 ASSERT(result == len); |
497 block_index += len; | 504 block_index += len; |
498 environment_block_[block_index++] = '\0'; | 505 environment_block_[block_index++] = '\0'; |
499 } | 506 } |
500 // Block-terminating zero char. | 507 // Block-terminating zero char. |
501 environment_block_[block_index++] = '\0'; | 508 environment_block_[block_index++] = '\0'; |
502 ASSERT(block_index == block_size); | 509 ASSERT(block_index == block_size); |
503 } | 510 } |
504 | 511 |
505 system_working_directory_ = NULL; | 512 system_working_directory_ = NULL; |
506 if (working_directory_ != NULL) { | 513 if (working_directory_ != NULL) { |
507 system_working_directory_ = | 514 system_working_directory_ = |
508 StringUtilsWin::Utf8ToWide(working_directory_); | 515 StringUtilsWin::Utf8ToWide(working_directory_); |
509 } | 516 } |
510 | 517 |
511 attribute_list_ = NULL; | 518 attribute_list_ = NULL; |
512 } | 519 } |
513 | 520 |
514 | 521 |
515 ~ProcessStarter() { | 522 ~ProcessStarter() { |
516 // Deallocate command-line and environment block strings. | |
517 delete[] command_line_; | |
518 delete[] environment_block_; | |
519 if (attribute_list_ != NULL) { | 523 if (attribute_list_ != NULL) { |
520 delete_proc_thread_attr_list(attribute_list_); | 524 delete_proc_thread_attr_list(attribute_list_); |
521 free(attribute_list_); | |
522 } | 525 } |
523 } | 526 } |
524 | 527 |
525 | 528 |
526 int Start() { | 529 int Start() { |
527 // Create pipes required. | 530 // Create pipes required. |
528 int err = CreatePipes(); | 531 int err = CreatePipes(); |
529 if (err != 0) return err; | 532 if (err != 0) { |
533 return err; | |
534 } | |
530 | 535 |
531 // Setup info structures. | 536 // Setup info structures. |
532 STARTUPINFOEXW startup_info; | 537 STARTUPINFOEXW startup_info; |
533 ZeroMemory(&startup_info, sizeof(startup_info)); | 538 ZeroMemory(&startup_info, sizeof(startup_info)); |
534 startup_info.StartupInfo.cb = sizeof(startup_info); | 539 startup_info.StartupInfo.cb = sizeof(startup_info); |
535 startup_info.StartupInfo.hStdInput = stdin_handles_[kReadHandle]; | 540 startup_info.StartupInfo.hStdInput = stdin_handles_[kReadHandle]; |
536 startup_info.StartupInfo.hStdOutput = stdout_handles_[kWriteHandle]; | 541 startup_info.StartupInfo.hStdOutput = stdout_handles_[kWriteHandle]; |
537 startup_info.StartupInfo.hStdError = stderr_handles_[kWriteHandle]; | 542 startup_info.StartupInfo.hStdError = stderr_handles_[kWriteHandle]; |
538 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES; | 543 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES; |
539 | 544 |
540 bool supports_proc_thread_attr_lists = EnsureInitialized(); | 545 bool supports_proc_thread_attr_lists = EnsureInitialized(); |
541 if (supports_proc_thread_attr_lists) { | 546 if (supports_proc_thread_attr_lists) { |
542 // Setup the handles to inherit. We only want to inherit the three handles | 547 // Setup the handles to inherit. We only want to inherit the three handles |
543 // for stdin, stdout and stderr. | 548 // for stdin, stdout and stderr. |
544 SIZE_T size = 0; | 549 SIZE_T size = 0; |
545 // The call to determine the size of an attribute list always fails with | 550 // The call to determine the size of an attribute list always fails with |
546 // ERROR_INSUFFICIENT_BUFFER and that error should be ignored. | 551 // ERROR_INSUFFICIENT_BUFFER and that error should be ignored. |
547 if (!init_proc_thread_attr_list(NULL, 1, 0, &size) && | 552 if (!init_proc_thread_attr_list(NULL, 1, 0, &size) && |
548 GetLastError() != ERROR_INSUFFICIENT_BUFFER) { | 553 (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) { |
549 return CleanupAndReturnError(); | 554 return CleanupAndReturnError(); |
550 } | 555 } |
551 attribute_list_ = | 556 attribute_list_ = reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>( |
zra
2016/03/15 18:12:29
ditto.
| |
552 reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(size)); | 557 Dart_ScopeAllocate(size)); |
553 ZeroMemory(attribute_list_, size); | 558 ZeroMemory(attribute_list_, size); |
554 if (!init_proc_thread_attr_list(attribute_list_, 1, 0, &size)) { | 559 if (!init_proc_thread_attr_list(attribute_list_, 1, 0, &size)) { |
555 return CleanupAndReturnError(); | 560 return CleanupAndReturnError(); |
556 } | 561 } |
557 static const int kNumInheritedHandles = 3; | 562 static const int kNumInheritedHandles = 3; |
558 HANDLE inherited_handles[kNumInheritedHandles] = | 563 HANDLE inherited_handles[kNumInheritedHandles] = |
559 { stdin_handles_[kReadHandle], | 564 { stdin_handles_[kReadHandle], |
560 stdout_handles_[kWriteHandle], | 565 stdout_handles_[kWriteHandle], |
561 stderr_handles_[kWriteHandle] }; | 566 stderr_handles_[kWriteHandle] }; |
562 if (!update_proc_thread_attr(attribute_list_, | 567 if (!update_proc_thread_attr(attribute_list_, |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
643 !CreateProcessPipe(stderr_handles_, pipe_names[2], kInheritWrite)) { | 648 !CreateProcessPipe(stderr_handles_, pipe_names[2], kInheritWrite)) { |
644 return CleanupAndReturnError(); | 649 return CleanupAndReturnError(); |
645 } | 650 } |
646 // Only open exit code pipe for non detached processes. | 651 // Only open exit code pipe for non detached processes. |
647 if (mode_ == kNormal) { | 652 if (mode_ == kNormal) { |
648 if (!CreateProcessPipe(exit_handles_, pipe_names[3], kInheritNone)) { | 653 if (!CreateProcessPipe(exit_handles_, pipe_names[3], kInheritNone)) { |
649 return CleanupAndReturnError(); | 654 return CleanupAndReturnError(); |
650 } | 655 } |
651 } | 656 } |
652 } else { | 657 } else { |
653 // Open NUL for stdin, stdout and stderr. | 658 // Open NUL for stdin, stdout, and stderr. |
654 if ((stdin_handles_[kReadHandle] = OpenNul()) == INVALID_HANDLE_VALUE || | 659 stdin_handles_[kReadHandle] = OpenNul(); |
655 (stdout_handles_[kWriteHandle] = OpenNul()) == INVALID_HANDLE_VALUE || | 660 if (stdin_handles_[kReadHandle] == INVALID_HANDLE_VALUE) { |
656 (stderr_handles_[kWriteHandle] = OpenNul()) == INVALID_HANDLE_VALUE) { | 661 return CleanupAndReturnError(); |
662 } | |
663 | |
664 stdout_handles_[kWriteHandle] = OpenNul(); | |
665 if (stdout_handles_[kWriteHandle] == INVALID_HANDLE_VALUE) { | |
666 return CleanupAndReturnError(); | |
667 } | |
668 | |
669 stderr_handles_[kWriteHandle] = OpenNul(); | |
670 if (stderr_handles_[kWriteHandle] == INVALID_HANDLE_VALUE) { | |
657 return CleanupAndReturnError(); | 671 return CleanupAndReturnError(); |
658 } | 672 } |
659 } | 673 } |
660 return 0; | 674 return 0; |
661 } | 675 } |
662 | 676 |
663 | 677 |
664 int CleanupAndReturnError() { | 678 int CleanupAndReturnError() { |
665 int error_code = SetOsErrorMessage(os_error_message_); | 679 int error_code = SetOsErrorMessage(os_error_message_); |
666 CloseProcessPipes( | 680 CloseProcessPipes( |
(...skipping 14 matching lines...) Expand all Loading... | |
681 | 695 |
682 const char* path_; | 696 const char* path_; |
683 const char* working_directory_; | 697 const char* working_directory_; |
684 ProcessStartMode mode_; | 698 ProcessStartMode mode_; |
685 intptr_t* in_; | 699 intptr_t* in_; |
686 intptr_t* out_; | 700 intptr_t* out_; |
687 intptr_t* err_; | 701 intptr_t* err_; |
688 intptr_t* id_; | 702 intptr_t* id_; |
689 intptr_t* exit_handler_; | 703 intptr_t* exit_handler_; |
690 char** os_error_message_; | 704 char** os_error_message_; |
705 | |
706 private: | |
707 DISALLOW_ALLOCATION(); | |
708 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter); | |
691 }; | 709 }; |
692 | 710 |
693 | 711 |
694 int Process::Start(const char* path, | 712 int Process::Start(const char* path, |
695 char* arguments[], | 713 char* arguments[], |
696 intptr_t arguments_length, | 714 intptr_t arguments_length, |
697 const char* working_directory, | 715 const char* working_directory, |
698 char* environment[], | 716 char* environment[], |
699 intptr_t environment_length, | 717 intptr_t environment_length, |
700 ProcessStartMode mode, | 718 ProcessStartMode mode, |
(...skipping 30 matching lines...) Expand all Loading... | |
731 ASSERT(read_pending_ == true); | 749 ASSERT(read_pending_ == true); |
732 data_size_ += size; | 750 data_size_ += size; |
733 free_size_ -= size; | 751 free_size_ -= size; |
734 ASSERT(free_size_ >= 0); | 752 ASSERT(free_size_ >= 0); |
735 read_pending_ = false; | 753 read_pending_ = false; |
736 } | 754 } |
737 | 755 |
738 // The access to the read buffer for overlapped read. | 756 // The access to the read buffer for overlapped read. |
739 void GetReadBuffer(uint8_t** buffer, intptr_t* size) { | 757 void GetReadBuffer(uint8_t** buffer, intptr_t* size) { |
740 ASSERT(!read_pending_); | 758 ASSERT(!read_pending_); |
741 if (free_size_ == 0) Allocate(); | 759 if (free_size_ == 0) { |
760 Allocate(); | |
761 } | |
742 ASSERT(free_size_ > 0); | 762 ASSERT(free_size_ > 0); |
743 ASSERT(free_size_ <= kBufferSize); | 763 ASSERT(free_size_ <= kBufferSize); |
744 *buffer = FreeSpaceAddress(); | 764 *buffer = FreeSpaceAddress(); |
745 *size = free_size_; | 765 *size = free_size_; |
746 read_pending_ = true; | 766 read_pending_ = true; |
747 } | 767 } |
748 | 768 |
749 intptr_t GetDataSize() { | 769 intptr_t GetDataSize() { |
750 return data_size_; | 770 return data_size_; |
751 } | 771 } |
752 | 772 |
753 uint8_t* GetFirstDataBuffer() { | 773 uint8_t* GetFirstDataBuffer() { |
754 ASSERT(head_ != NULL); | 774 ASSERT(head_ != NULL); |
755 ASSERT(head_ == tail_); | 775 ASSERT(head_ == tail_); |
756 ASSERT(data_size_ <= kBufferSize); | 776 ASSERT(data_size_ <= kBufferSize); |
757 return head_->data_; | 777 return head_->data_; |
758 } | 778 } |
759 | 779 |
760 void FreeDataBuffer() { | 780 void FreeDataBuffer() { |
761 Free(); | 781 Free(); |
762 } | 782 } |
763 | 783 |
764 private: | 784 private: |
765 bool read_pending_; | 785 bool read_pending_; |
786 | |
787 DISALLOW_COPY_AND_ASSIGN(BufferList); | |
766 }; | 788 }; |
767 | 789 |
768 | 790 |
769 class OverlappedHandle { | 791 class OverlappedHandle { |
770 public: | 792 public: |
793 OverlappedHandle() {} | |
794 | |
771 void Init(HANDLE handle, HANDLE event) { | 795 void Init(HANDLE handle, HANDLE event) { |
772 handle_ = handle; | 796 handle_ = handle; |
773 event_ = event; | 797 event_ = event; |
774 ClearOverlapped(); | 798 ClearOverlapped(); |
775 } | 799 } |
776 | 800 |
777 bool HasEvent(HANDLE event) { | 801 bool HasEvent(HANDLE event) { |
778 return event_ == event; | 802 return (event_ == event); |
779 } | 803 } |
780 | 804 |
781 bool Read() { | 805 bool Read() { |
782 // Get the data read as a result of a completed overlapped operation. | 806 // Get the data read as a result of a completed overlapped operation. |
783 if (overlapped_.InternalHigh > 0) { | 807 if (overlapped_.InternalHigh > 0) { |
784 buffer_.DataIsRead(overlapped_.InternalHigh); | 808 buffer_.DataIsRead(overlapped_.InternalHigh); |
785 } else { | 809 } else { |
786 buffer_.DataIsRead(0); | 810 buffer_.DataIsRead(0); |
787 } | 811 } |
788 | 812 |
789 // Keep reading until error or pending operation. | 813 // Keep reading until error or pending operation. |
790 while (true) { | 814 while (true) { |
791 ClearOverlapped(); | 815 ClearOverlapped(); |
792 uint8_t* buffer; | 816 uint8_t* buffer; |
793 intptr_t buffer_size; | 817 intptr_t buffer_size; |
794 buffer_.GetReadBuffer(&buffer, &buffer_size); | 818 buffer_.GetReadBuffer(&buffer, &buffer_size); |
795 BOOL ok = ReadFile(handle_, buffer, buffer_size, NULL, &overlapped_); | 819 BOOL ok = ReadFile(handle_, buffer, buffer_size, NULL, &overlapped_); |
796 if (!ok) return GetLastError() == ERROR_IO_PENDING; | 820 if (!ok) { |
821 return (GetLastError() == ERROR_IO_PENDING); | |
822 } | |
797 buffer_.DataIsRead(overlapped_.InternalHigh); | 823 buffer_.DataIsRead(overlapped_.InternalHigh); |
798 } | 824 } |
799 } | 825 } |
800 | 826 |
801 Dart_Handle GetData() { | 827 Dart_Handle GetData() { |
802 return buffer_.GetData(); | 828 return buffer_.GetData(); |
803 } | 829 } |
804 | 830 |
805 intptr_t GetDataSize() { | 831 intptr_t GetDataSize() { |
806 return buffer_.GetDataSize(); | 832 return buffer_.GetDataSize(); |
(...skipping 19 matching lines...) Expand all Loading... | |
826 memset(&overlapped_, 0, sizeof(overlapped_)); | 852 memset(&overlapped_, 0, sizeof(overlapped_)); |
827 overlapped_.hEvent = event_; | 853 overlapped_.hEvent = event_; |
828 } | 854 } |
829 | 855 |
830 OVERLAPPED overlapped_; | 856 OVERLAPPED overlapped_; |
831 HANDLE handle_; | 857 HANDLE handle_; |
832 HANDLE event_; | 858 HANDLE event_; |
833 BufferList buffer_; | 859 BufferList buffer_; |
834 | 860 |
835 DISALLOW_ALLOCATION(); | 861 DISALLOW_ALLOCATION(); |
862 DISALLOW_COPY_AND_ASSIGN(OverlappedHandle); | |
836 }; | 863 }; |
837 | 864 |
838 | 865 |
839 bool Process::Wait(intptr_t pid, | 866 bool Process::Wait(intptr_t pid, |
840 intptr_t in, | 867 intptr_t in, |
841 intptr_t out, | 868 intptr_t out, |
842 intptr_t err, | 869 intptr_t err, |
843 intptr_t exit_event, | 870 intptr_t exit_event, |
844 ProcessResult* result) { | 871 ProcessResult* result) { |
845 // Close input to the process right away. | 872 // Close input to the process right away. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
898 } | 925 } |
899 } | 926 } |
900 } | 927 } |
901 | 928 |
902 // All handles closed and all data read. | 929 // All handles closed and all data read. |
903 result->set_stdout_data(oh[0].GetData()); | 930 result->set_stdout_data(oh[0].GetData()); |
904 result->set_stderr_data(oh[1].GetData()); | 931 result->set_stderr_data(oh[1].GetData()); |
905 | 932 |
906 // Calculate the exit code. | 933 // Calculate the exit code. |
907 ASSERT(oh[2].GetDataSize() == 8); | 934 ASSERT(oh[2].GetDataSize() == 8); |
908 uint32_t exit[2]; | 935 uint32_t exit_codes[2]; |
909 memmove(&exit, oh[2].GetFirstDataBuffer(), sizeof(exit)); | 936 memmove(&exit_codes, oh[2].GetFirstDataBuffer(), sizeof(exit_codes)); |
910 oh[2].FreeDataBuffer(); | 937 oh[2].FreeDataBuffer(); |
911 intptr_t exit_code = exit[0]; | 938 intptr_t exit_code = exit_codes[0]; |
912 intptr_t negative = exit[1]; | 939 intptr_t negative = exit_codes[1]; |
913 if (negative) exit_code = -exit_code; | 940 if (negative) { |
941 exit_code = -exit_code; | |
942 } | |
914 result->set_exit_code(exit_code); | 943 result->set_exit_code(exit_code); |
915 return true; | 944 return true; |
916 } | 945 } |
917 | 946 |
918 | 947 |
919 bool Process::Kill(intptr_t id, int signal) { | 948 bool Process::Kill(intptr_t id, int signal) { |
920 USE(signal); // signal is not used on Windows. | 949 USE(signal); // signal is not used on Windows. |
921 HANDLE process_handle; | 950 HANDLE process_handle; |
922 HANDLE wait_handle; | 951 HANDLE wait_handle; |
923 HANDLE exit_pipe; | 952 HANDLE exit_pipe; |
924 // First check the process info list for the process to get a handle to it. | 953 // First check the process info list for the process to get a handle to it. |
925 bool success = ProcessInfoList::LookupProcess(id, | 954 bool success = ProcessInfoList::LookupProcess(id, |
926 &process_handle, | 955 &process_handle, |
927 &wait_handle, | 956 &wait_handle, |
928 &exit_pipe); | 957 &exit_pipe); |
929 // For detached processes we don't have the process registered in the | 958 // For detached processes we don't have the process registered in the |
930 // process info list. Try to look it up through the OS. | 959 // process info list. Try to look it up through the OS. |
931 if (!success) { | 960 if (!success) { |
932 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, id); | 961 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, id); |
933 // The process is already dead. | 962 // The process is already dead. |
934 if (process_handle == INVALID_HANDLE_VALUE) return false; | 963 if (process_handle == INVALID_HANDLE_VALUE) { |
964 return false; | |
965 } | |
935 } | 966 } |
936 BOOL result = TerminateProcess(process_handle, -1); | 967 BOOL result = TerminateProcess(process_handle, -1); |
937 return result ? true : false; | 968 return result ? true : false; |
938 } | 969 } |
939 | 970 |
940 | 971 |
941 void Process::TerminateExitCodeHandler() { | 972 void Process::TerminateExitCodeHandler() { |
942 // Nothing needs to be done on Windows. | 973 // Nothing needs to be done on Windows. |
943 } | 974 } |
944 | 975 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
978 case kSighup: return CTRL_CLOSE_EVENT; | 1009 case kSighup: return CTRL_CLOSE_EVENT; |
979 case kSigint: return CTRL_C_EVENT; | 1010 case kSigint: return CTRL_C_EVENT; |
980 default: | 1011 default: |
981 return -1; | 1012 return -1; |
982 } | 1013 } |
983 } | 1014 } |
984 | 1015 |
985 | 1016 |
986 intptr_t Process::SetSignalHandler(intptr_t signal) { | 1017 intptr_t Process::SetSignalHandler(intptr_t signal) { |
987 signal = GetWinSignal(signal); | 1018 signal = GetWinSignal(signal); |
988 if (signal == -1) return -1; | 1019 if (signal == -1) { |
1020 return -1; | |
1021 } | |
989 | 1022 |
990 // Generate a unique pipe name for the named pipe. | 1023 // Generate a unique pipe name for the named pipe. |
991 wchar_t pipe_name[kMaxPipeNameSize]; | 1024 wchar_t pipe_name[kMaxPipeNameSize]; |
992 int status = GenerateNames<1>(&pipe_name); | 1025 int status = GenerateNames<1>(&pipe_name); |
993 if (status != 0) return status; | 1026 if (status != 0) { |
1027 return status; | |
1028 } | |
994 | 1029 |
995 HANDLE fds[2]; | 1030 HANDLE fds[2]; |
996 if (!CreateProcessPipe(fds, pipe_name, kInheritNone)) { | 1031 if (!CreateProcessPipe(fds, pipe_name, kInheritNone)) { |
997 int error_code = GetLastError(); | 1032 int error_code = GetLastError(); |
998 CloseProcessPipe(fds); | 1033 CloseProcessPipe(fds); |
999 SetLastError(error_code); | 1034 SetLastError(error_code); |
1000 return -1; | 1035 return -1; |
1001 } | 1036 } |
1002 MutexLocker lock(signal_mutex); | 1037 MutexLocker lock(signal_mutex); |
1003 FileHandle* write_handle = new FileHandle(fds[kWriteHandle]); | 1038 FileHandle* write_handle = new FileHandle(fds[kWriteHandle]); |
1004 write_handle->EnsureInitialized(EventHandler::delegate()); | 1039 write_handle->EnsureInitialized(EventHandler::delegate()); |
1005 intptr_t write_fd = reinterpret_cast<intptr_t>(write_handle); | 1040 intptr_t write_fd = reinterpret_cast<intptr_t>(write_handle); |
1006 if (signal_handlers == NULL) { | 1041 if (signal_handlers == NULL) { |
1007 if (SetConsoleCtrlHandler(SignalHandler, true) == 0) { | 1042 if (SetConsoleCtrlHandler(SignalHandler, true) == 0) { |
1008 int error_code = GetLastError(); | 1043 int error_code = GetLastError(); |
1009 delete write_handle; | 1044 delete write_handle; |
1010 CloseProcessPipe(fds); | 1045 CloseProcessPipe(fds); |
1011 SetLastError(error_code); | 1046 SetLastError(error_code); |
1012 return -1; | 1047 return -1; |
1013 } | 1048 } |
1014 } | 1049 } |
1015 signal_handlers = new SignalInfo(write_fd, signal, signal_handlers); | 1050 signal_handlers = new SignalInfo(write_fd, signal, signal_handlers); |
1016 return reinterpret_cast<intptr_t>(new FileHandle(fds[kReadHandle])); | 1051 return reinterpret_cast<intptr_t>(new FileHandle(fds[kReadHandle])); |
1017 } | 1052 } |
1018 | 1053 |
1019 | 1054 |
1020 void Process::ClearSignalHandler(intptr_t signal) { | 1055 void Process::ClearSignalHandler(intptr_t signal) { |
1021 signal = GetWinSignal(signal); | 1056 signal = GetWinSignal(signal); |
1022 if (signal == -1) return; | 1057 if (signal == -1) { |
1058 return; | |
1059 } | |
1023 MutexLocker lock(signal_mutex); | 1060 MutexLocker lock(signal_mutex); |
1024 SignalInfo* handler = signal_handlers; | 1061 SignalInfo* handler = signal_handlers; |
1025 while (handler != NULL) { | 1062 while (handler != NULL) { |
1026 if (handler->port() == Dart_GetMainPortId() && | 1063 if ((handler->port() == Dart_GetMainPortId()) && |
1027 handler->signal() == signal) { | 1064 (handler->signal() == signal)) { |
1028 handler->Unlink(); | 1065 handler->Unlink(); |
1029 break; | 1066 break; |
1030 } | 1067 } |
1031 handler = handler->next(); | 1068 handler = handler->next(); |
1032 } | 1069 } |
1033 if (handler != NULL) { | 1070 if (handler != NULL) { |
1034 if (signal_handlers == handler) { | 1071 if (signal_handlers == handler) { |
1035 signal_handlers = handler->next(); | 1072 signal_handlers = handler->next(); |
1036 } | 1073 } |
1037 if (signal_handlers == NULL) { | 1074 if (signal_handlers == NULL) { |
1038 USE(SetConsoleCtrlHandler(SignalHandler, false)); | 1075 USE(SetConsoleCtrlHandler(SignalHandler, false)); |
1039 } | 1076 } |
1040 } | 1077 } |
1041 delete handler; | 1078 delete handler; |
1042 } | 1079 } |
1043 | 1080 |
1044 } // namespace bin | 1081 } // namespace bin |
1045 } // namespace dart | 1082 } // namespace dart |
1046 | 1083 |
1047 #endif // defined(TARGET_OS_WINDOWS) | 1084 #endif // defined(TARGET_OS_WINDOWS) |
OLD | NEW |