Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(190)

Side by Side Diff: runtime/bin/process_win.cc

Issue 1800863002: Cleanup in //runtime/bin (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Windows fixes Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698