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

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

Issue 9310053: Rework Windows process handling. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix Linux and Mac Created 8 years, 10 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 | Annotate | Revision Log
« runtime/bin/process_macos.cc ('K') | « runtime/bin/process_macos.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <process.h> 5 #include <process.h>
6 6
7 #include "bin/builtin.h" 7 #include "bin/builtin.h"
8 #include "bin/process.h" 8 #include "bin/process.h"
9 #include "bin/eventhandler.h" 9 #include "bin/eventhandler.h"
10 #include "bin/thread.h"
10 #include "platform/globals.h" 11 #include "platform/globals.h"
11 12
12 static const int kReadHandle = 0; 13 static const int kReadHandle = 0;
13 static const int kWriteHandle = 1; 14 static const int kWriteHandle = 1;
14 15
16
17 // ProcessInfo is used to map a process id to the process handle and
18 // the pipe used to communicate the exit code of the process to Dart.
19 // ProcessInfo objects are kept in the static singly-linked
20 // ProcessInfoList.
15 class ProcessInfo { 21 class ProcessInfo {
16 public: 22 public:
17 ProcessInfo(DWORD process_id, HANDLE process_handle, HANDLE exit_pipe) 23 ProcessInfo(DWORD process_id, HANDLE process_handle, HANDLE exit_pipe)
18 : process_id_(process_id), 24 : process_id_(process_id),
19 process_handle_(process_handle), 25 process_handle_(process_handle),
20 exit_pipe_(exit_pipe) { } 26 exit_pipe_(exit_pipe) { }
21 27
22 intptr_t pid() { return process_id_; } 28 ~ProcessInfo() {
29 BOOL success = CloseHandle(process_handle_);
30 if (!success) {
31 FATAL("Failed to close process handle");
32 }
33 success = CloseHandle(exit_pipe_);
34 if (!success) {
35 FATAL("Failed to close process exit code pipe");
36 }
37 }
38
39 DWORD pid() { return process_id_; }
23 HANDLE process_handle() { return process_handle_; } 40 HANDLE process_handle() { return process_handle_; }
24 HANDLE exit_pipe() { return exit_pipe_; } 41 HANDLE exit_pipe() { return exit_pipe_; }
25 ProcessInfo* next() { return next_; } 42 ProcessInfo* next() { return next_; }
26 void set_next(ProcessInfo* next) { next_ = next; } 43 void set_next(ProcessInfo* next) { next_ = next; }
27 44
28 private: 45 private:
29 DWORD process_id_; // Process id. 46 DWORD process_id_; // Process id.
30 HANDLE process_handle_; // Process handle. 47 HANDLE process_handle_; // Process handle.
31 HANDLE exit_pipe_; // File descriptor for pipe to report exit code. 48 HANDLE exit_pipe_; // File descriptor for pipe to report exit code.
32 ProcessInfo* next_; 49 ProcessInfo* next_;
33 }; 50 };
34 51
35 52
36 ProcessInfo* active_processes = NULL; 53 // Singly-linked list of ProcessInfo objects for all active processes
37 54 // started from Dart.
38 55 class ProcessInfoList {
39 static void AddProcess(ProcessInfo* process) { 56 public:
40 process->set_next(active_processes); 57 static void AddProcess(DWORD pid, HANDLE handle, HANDLE pipe) {
41 active_processes = process; 58 MutexLocker locker(&mutex_);
42 } 59 ProcessInfo* info = new ProcessInfo(pid, handle, pipe);
43 60 info->set_next(active_processes_);
44 61 active_processes_ = info;
45 static ProcessInfo* LookupProcess(intptr_t pid) { 62 ++number_of_processes_;
46 ProcessInfo* current = active_processes; 63 BOOL success = SetEvent(GetProcessAddedEvent());
47 while (current != NULL) { 64 if (!success) {
48 if (current->pid() == pid) { 65 FATAL("Failed to set process added event");
49 return current; 66 }
50 } 67 }
51 current = current->next(); 68
52 } 69 static bool LookupProcess(DWORD pid, HANDLE* handle, HANDLE* pipe) {
53 return NULL; 70 MutexLocker locker(&mutex_);
54 } 71 ProcessInfo* current = active_processes_;
55 72 while (current != NULL) {
56 73 if (current->pid() == pid) {
57 static void RemoveProcess(intptr_t pid) { 74 *handle = current->process_handle();
58 ProcessInfo* prev = NULL; 75 *pipe = current->exit_pipe();
59 ProcessInfo* current = active_processes; 76 return true;
60 while (current != NULL) { 77 }
61 if (current->pid() == pid) { 78 current = current->next();
62 if (prev == NULL) { 79 }
63 active_processes = current->next(); 80 return false;
81 }
82
83 static DWORD LookupProcessByHandle(HANDLE handle, DWORD* pid, HANDLE* pipe) {
Søren Gjesse 2012/02/02 12:26:07 bool return type.
Mads Ager (google) 2012/02/02 13:47:45 Good catch. Thanks.
84 MutexLocker locker(&mutex_);
85 ProcessInfo* current = active_processes_;
86 while (current != NULL) {
87 if (current->process_handle() == handle) {
88 *pid = current->pid();
89 *pipe = current->exit_pipe();
90 return true;
91 }
92 current = current->next();
93 }
94 return false;
95 }
96
97 static void RemoveProcess(DWORD pid) {
98 MutexLocker locker(&mutex_);
99 ProcessInfo* prev = NULL;
100 ProcessInfo* current = active_processes_;
101 while (current != NULL) {
102 if (current->pid() == pid) {
103 if (prev == NULL) {
104 active_processes_ = current->next();
105 } else {
106 prev->set_next(current->next());
107 }
108 delete current;
109 --number_of_processes_;
110 return;
111 }
112 prev = current;
113 current = current->next();
114 }
115 }
116
117 static void GetHandleArray(HANDLE** handles,
118 DWORD* number_of_handles,
119 intptr_t prefix_size) {
120 MutexLocker locker(&mutex_);
121 ASSERT(prefix_size >= 0);
122 *number_of_handles = prefix_size + number_of_processes_;
123 *handles = new HANDLE[*number_of_handles];
124 intptr_t i = prefix_size;
125 ProcessInfo* current = active_processes_;
126 while (current != NULL) {
127 (*handles)[i++] = current->process_handle();
128 current = current->next();
129 }
130 ASSERT(i == *number_of_handles);
131 // We have taken a new snapshot of the handles in the list. Reset
132 // the process_added_event so we will get signaled if more
133 // processes are added.
134 BOOL success = ResetEvent(GetProcessAddedEvent());
135 if (!success) {
136 FATAL("Failed to reset process added event");
137 }
138 }
139
140 private:
141 friend class ExitCodeHandler;
142 static HANDLE GetProcessAddedEvent() {
143 MutexLocker locker(&process_added_event_mutex_);
144 if (process_added_event_ == 0) {
Søren Gjesse 2012/02/02 12:26:07 INVALID_HANDLE_VALUE instead of 0.
Mads Ager (google) 2012/02/02 13:47:45 Done.
145 process_added_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
146 if (process_added_event_ == NULL) {
Søren Gjesse 2012/02/02 12:26:07 INVALID_HANDLE_VALUE instead of NULL.
Mads Ager (google) 2012/02/02 13:47:45 Not on this one. Strange, I agree, but that's what
147 FATAL("Failed to allocate event for signaling addition of processes");
148 }
149 }
150 return process_added_event_;
151 }
152 // Number of processes currently in the list.
153 static intptr_t number_of_processes_;
154 // Linked list of ProcessInfo objects for all active processes
155 // started from Dart code.
156 static ProcessInfo* active_processes_;
157 // Mutex protecting all accesses to the linked list of active
158 // processes.
159 static dart::Mutex mutex_;
160 // Event used to signal that more processes have been added to the
161 // list.
162 static HANDLE process_added_event_;
163 static dart::Mutex process_added_event_mutex_;
164 };
165
166
167 intptr_t ProcessInfoList::number_of_processes_ = 0;
168 ProcessInfo* ProcessInfoList::active_processes_ = NULL;
169 dart::Mutex ProcessInfoList::mutex_;
170 HANDLE ProcessInfoList::process_added_event_ = 0;
Søren Gjesse 2012/02/02 12:26:07 INVALID_HANDLE_VALUE instead of 0.
Mads Ager (google) 2012/02/02 13:47:45 Done.
171 dart::Mutex ProcessInfoList::process_added_event_mutex_;
172
173
174 // The exit code handler sets up a separate thread which is waiting
175 // for Dart process termination and process start. When a process
176 // terminates the exit code is extracted and communicated to Dart
177 // through the event loop.
178 class ExitCodeHandler {
179 public:
180 // Ensure that the ExitCodeHandler has been initialized.
181 static bool EnsureInitialized() {
182 // Multiple isolates could be starting processes at the same
183 // time. Make sure that only one of them initializes the
184 // ExitCodeHandler.
185 MutexLocker locker(&mutex_);
186 if (initialized_) {
187 return true;
188 }
189
190 // Allocate an event object to be signaled when the exit code
191 // thread should terminate.
192 terminate_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
193 if (terminate_event_ == NULL) {
Søren Gjesse 2012/02/02 12:26:07 INVALID_HANDLE_VALUE instead of NULL.
Mads Ager (google) 2012/02/02 13:47:45 Not for this one according to CreateEvent document
194 return false;
195 }
196
197 // Start thread that waits for the process-addition and
198 // thread-termination events as well as all process handles for
199 // all active processes.
200 HANDLE* events = new HANDLE[2];
201 events[0] = ProcessInfoList::GetProcessAddedEvent();
202 events[1] = terminate_event_;
203 new dart::Thread(ExitCodeHandlerEntry, reinterpret_cast<uword>(events));
Søren Gjesse 2012/02/02 12:26:07 int result = dart::Thread::Start(ExitCodeHandlerEn
Mads Ager (google) 2012/02/02 13:47:45 Done.
204
205 // Thread started and the ExitCodeHandler is initialized.
206 initialized_ = true;
207 return true;
208 }
209
210 static void TerminateExitCodeThread() {
Søren Gjesse 2012/02/02 12:26:07 Maybe add a comment for this function that it actu
Mads Ager (google) 2012/02/02 13:47:45 Yes, that comment is in the process.h file. :)
211 MutexLocker locker(&mutex_);
212 if (!initialized_) {
213 return;
214 }
215
216 BOOL success = SetEvent(terminate_event_);
217 if (!success) {
218 FATAL("Failed to set terminate event for exit code handler shutdown");
219 }
220
221 {
222 MonitorLocker terminate_locker(&thread_terminate_monitor_);
223 while (!thread_terminated_) {
224 terminate_locker.Wait();
225 }
226 }
227 }
228
229 static void ExitCodeThreadTerminated() {
230 MonitorLocker locker(&thread_terminate_monitor_);
231 thread_terminated_ = true;
232 locker.Notify();
233 }
234
235 private:
236 // Entry point for the exit code handler thread started by the
237 // ExitCodeHandler.
238 static void ExitCodeHandlerEntry(uword param) {
239 HANDLE* events = reinterpret_cast<HANDLE*>(param);
240 HANDLE wake_up_event = events[0];
241 HANDLE terminate_event = events[1];
242 delete[] events;
243
244 while (true) {
245 // Get the list of handles to wait for. Allocate a prefix of two
246 // extra handles for the 'process added' and 'thread
247 // termination' event objects.
248 HANDLE* handles;
Søren Gjesse 2012/02/02 12:26:07 How about just declaring this as HANDLE handles[M
Mads Ager (google) 2012/02/02 13:47:45 Done. It needs to be dealt with in GetHandleArray
249 DWORD number_of_handles;
250 intptr_t prefix_size = 2;
251 ProcessInfoList::GetHandleArray(&handles,
252 &number_of_handles,
253 prefix_size);
254 handles[0] = wake_up_event;
255 handles[1] = terminate_event;
256
257 // TODO(1450): support more than 63 processes on Windows.
258 if (number_of_handles > MAXIMUM_WAIT_OBJECTS) {
259 FATAL1("Only %d processes supported on Windows at this point\n",
260 MAXIMUM_WAIT_OBJECTS - 1);
261 }
262
263 // Wait for the handles.
264 DWORD result =
265 WaitForMultipleObjects(number_of_handles, handles, FALSE, INFINITE);
266 if (result == WAIT_FAILED) {
267 FATAL("Failed to wait for multiple objects for exit code handling");
268 }
269
270 if (result == 0) {
271 // If the result is 0 the thread woke up because of process
272 // addition. We don't have to do anything we just need to
273 // update the list of handles we are waiting for.
274 } else if (result == 1) {
275 // The termination event was triggered. Free handle array and
276 // exit.
277 delete[] handles;
278 CloseHandle(terminate_event_);
279 CloseHandle(wake_up_event);
280 ExitCodeThreadTerminated();
281 return;
64 } else { 282 } else {
65 prev->set_next(current->next()); 283 // The result is the index of the process that was
66 } 284 // signalled. Get its exit code and communicate it to Dart.
67 delete current; 285 ASSERT(result < number_of_handles);
68 return; 286 int exit_code;
69 } 287 BOOL ok = GetExitCodeProcess(handles[result],
70 prev = current; 288 reinterpret_cast<DWORD*>(&exit_code));
71 current = current->next(); 289 if (!ok) {
72 } 290 FATAL1("GetExitCodeProcess failed %d\n", GetLastError());
73 } 291 }
292 int negative = 0;
293 if (exit_code < 0) {
294 exit_code = abs(exit_code);
295 negative = 1;
296 }
297
298 DWORD pid;
299 HANDLE exit_pipe;
300 bool success = ProcessInfoList::LookupProcessByHandle(handles[result],
301 &pid,
302 &exit_pipe);
303 if (!success) {
304 FATAL("Failed to lookup pid and exit pipe from process handle");
305 }
306 int message[2] = { exit_code, negative };
307 DWORD written;
308 ok = WriteFile(exit_pipe, message, sizeof(message), &written, NULL);
309 // If the process has been closed, the read end of the exit
310 // pipe has been closed. It is therefore not a problem that
311 // WriteFile fails with a closed pipe error
312 // (ERROR_NO_DATA). Other errors should not happen.
313 if (ok && written != sizeof(message)) {
314 FATAL("Failed to write entire process exit message");
315 } else if (!ok && GetLastError() != ERROR_NO_DATA) {
316 FATAL1("Failed to write exit code: %d", GetLastError());
317 }
318 ProcessInfoList::RemoveProcess(pid);
319 }
320 delete[] handles;
321 }
322 }
323
324 static dart::Mutex mutex_;
325 static bool initialized_;
326 static HANDLE terminate_event_;
327 static bool thread_terminated_;
328 static dart::Monitor thread_terminate_monitor_;
329 };
330
331
332 dart::Mutex ExitCodeHandler::mutex_;
333 bool ExitCodeHandler::initialized_ = false;
334 HANDLE ExitCodeHandler::terminate_event_ = 0;
Søren Gjesse 2012/02/02 12:26:07 INVALID_HANDLE_VALUE instead of 0.
Mads Ager (google) 2012/02/02 13:47:45 Done.
335 bool ExitCodeHandler::thread_terminated_ = false;
336 dart::Monitor ExitCodeHandler::thread_terminate_monitor_;
74 337
75 338
76 // Types of pipes to create. 339 // Types of pipes to create.
77 enum NamedPipeType { 340 enum NamedPipeType {
78 kInheritRead, 341 kInheritRead,
79 kInheritWrite, 342 kInheritWrite,
80 kInheritNone 343 kInheritNone
81 }; 344 };
82 345
83 346
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { 457 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
195 fprintf(stderr, "FormatMessage failed %d\n", GetLastError()); 458 fprintf(stderr, "FormatMessage failed %d\n", GetLastError());
196 } 459 }
197 snprintf(os_error_message, os_error_message_len, "OS Error %d", error_code); 460 snprintf(os_error_message, os_error_message_len, "OS Error %d", error_code);
198 } 461 }
199 os_error_message[os_error_message_len - 1] = '\0'; 462 os_error_message[os_error_message_len - 1] = '\0';
200 return error_code; 463 return error_code;
201 } 464 }
202 465
203 466
204 static unsigned int __stdcall TerminationWaitThread(void* args) {
205 ProcessInfo* process = reinterpret_cast<ProcessInfo*>(args);
206 WaitForSingleObject(process->process_handle(), INFINITE);
207 int exit_code;
208 BOOL ok = GetExitCodeProcess(process->process_handle(),
209 reinterpret_cast<DWORD*>(&exit_code));
210 if (!ok) {
211 fprintf(stderr, "GetExitCodeProcess failed %d\n", GetLastError());
212 }
213 int negative = 0;
214 if (exit_code < 0) {
215 exit_code = abs(exit_code);
216 negative = 1;
217 }
218 int message[3] = { process->pid(), exit_code, negative };
219 DWORD written;
220 ok = WriteFile(
221 process->exit_pipe(), message, sizeof(message), &written, NULL);
222 if (!ok || written != sizeof(message)) {
223 fprintf(stderr, "WriteFile failed %d\n", GetLastError());
224 }
225 return 0;
226 }
227
228
229 int Process::Start(const char* path, 467 int Process::Start(const char* path,
230 char* arguments[], 468 char* arguments[],
231 intptr_t arguments_length, 469 intptr_t arguments_length,
232 const char* working_directory, 470 const char* working_directory,
233 intptr_t* in, 471 intptr_t* in,
234 intptr_t* out, 472 intptr_t* out,
235 intptr_t* err, 473 intptr_t* err,
236 intptr_t* id, 474 intptr_t* id,
237 intptr_t* exit_handler, 475 intptr_t* exit_handler,
238 char* os_error_message, 476 char* os_error_message,
239 int os_error_message_len) { 477 int os_error_message_len) {
478 // Ensure that the process exit handler thread has been started.
479 bool initialized = ExitCodeHandler::EnsureInitialized();
480 if (!initialized) {
481 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len);
482 fprintf(stderr, "Failed to initialize ExitCodeHandler: %d\n", error_code);
483 return error_code;
484 }
485
240 HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; 486 HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
241 HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; 487 HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
242 HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; 488 HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
243 HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; 489 HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
244 490
245 // Generate unique pipe names for the four named pipes needed. 491 // Generate unique pipe names for the four named pipes needed.
246 char pipe_names[4][80]; 492 char pipe_names[4][80];
247 UUID uuid; 493 UUID uuid;
248 RPC_STATUS status = UuidCreateSequential(&uuid); 494 RPC_STATUS status = UuidCreateSequential(&uuid);
249 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { 495 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) {
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 // Deallocate command-line string. 600 // Deallocate command-line string.
355 delete[] command_line; 601 delete[] command_line;
356 602
357 if (result == 0) { 603 if (result == 0) {
358 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len); 604 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len);
359 CloseProcessPipes( 605 CloseProcessPipes(
360 stdin_handles, stdout_handles, stderr_handles, exit_handles); 606 stdin_handles, stdout_handles, stderr_handles, exit_handles);
361 return error_code; 607 return error_code;
362 } 608 }
363 609
364 ProcessInfo* process = new ProcessInfo(process_info.dwProcessId, 610 ProcessInfoList::AddProcess(process_info.dwProcessId,
365 process_info.hProcess, 611 process_info.hProcess,
366 exit_handles[kWriteHandle]); 612 exit_handles[kWriteHandle]);
367 AddProcess(process);
368
369 // TODO(sgjesse): Don't use a separate thread for waiting for each process to
370 // terminate.
371 uint32_t tid;
372 uintptr_t thread_handle =
373 _beginthreadex(NULL, 32 * 1024, TerminationWaitThread, process, 0, &tid);
374 if (thread_handle == -1) {
375 FATAL("Failed to start process termination wait thread");
376 }
377 613
378 // Connect the three std streams. 614 // Connect the three std streams.
379 FileHandle* stdin_handle = new FileHandle(stdin_handles[kWriteHandle]); 615 FileHandle* stdin_handle = new FileHandle(stdin_handles[kWriteHandle]);
380 CloseHandle(stdin_handles[kReadHandle]); 616 CloseHandle(stdin_handles[kReadHandle]);
381 FileHandle* stdout_handle = new FileHandle(stdout_handles[kReadHandle]); 617 FileHandle* stdout_handle = new FileHandle(stdout_handles[kReadHandle]);
382 CloseHandle(stdout_handles[kWriteHandle]); 618 CloseHandle(stdout_handles[kWriteHandle]);
383 FileHandle* stderr_handle = new FileHandle(stderr_handles[kReadHandle]); 619 FileHandle* stderr_handle = new FileHandle(stderr_handles[kReadHandle]);
384 CloseHandle(stderr_handles[kWriteHandle]); 620 CloseHandle(stderr_handles[kWriteHandle]);
385 FileHandle* exit_handle = new FileHandle(exit_handles[kReadHandle]); 621 FileHandle* exit_handle = new FileHandle(exit_handles[kReadHandle]);
386 *in = reinterpret_cast<intptr_t>(stdout_handle); 622 *in = reinterpret_cast<intptr_t>(stdout_handle);
387 *out = reinterpret_cast<intptr_t>(stdin_handle); 623 *out = reinterpret_cast<intptr_t>(stdin_handle);
388 *err = reinterpret_cast<intptr_t>(stderr_handle); 624 *err = reinterpret_cast<intptr_t>(stderr_handle);
389 *exit_handler = reinterpret_cast<intptr_t>(exit_handle); 625 *exit_handler = reinterpret_cast<intptr_t>(exit_handle);
390 626
391 CloseHandle(process_info.hThread); 627 CloseHandle(process_info.hThread);
392 628
393 // Return process id. 629 // Return process id.
394 *id = process->pid(); 630 *id = process_info.dwProcessId;
395 return 0; 631 return 0;
396 } 632 }
397 633
398 634
399 bool Process::Kill(intptr_t id) { 635 bool Process::Kill(intptr_t id) {
400 ProcessInfo* process = LookupProcess(id); 636 HANDLE process_handle;
401 ASSERT(process != NULL); 637 HANDLE exit_pipe;
402 if (process != NULL) { 638 bool success =
403 BOOL result = TerminateProcess(process->process_handle(), -1); 639 ProcessInfoList::LookupProcess(id, &process_handle, &exit_pipe);
404 if (result == 0) { 640 ASSERT(success);
405 return false; 641 BOOL result = TerminateProcess(process_handle, -1);
406 } 642 if (!result) {
643 return false;
407 } 644 }
408 return true; 645 return true;
409 } 646 }
410 647
411 648
412 void Process::Exit(intptr_t id) { 649 void Process::TerminateExitCodeHandler() {
413 RemoveProcess(id); 650 ExitCodeHandler::TerminateExitCodeThread();
414 } 651 }
415
416
417 void Process::TerminateExitCodeHandler() {
418 // TODO(ager): Implement.
419 }
OLDNEW
« runtime/bin/process_macos.cc ('K') | « runtime/bin/process_macos.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698