| 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 <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 bool LookupProcessByHandle(HANDLE handle, DWORD* pid, HANDLE* pipe) { |
| 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 // Extract the process handles from the process list. The handles |
| 118 // array argument must have space for MAXIMUM_WAIT_OBJECTS handles. |
| 119 static DWORD GetHandleArray(HANDLE* handles, intptr_t prefix_size) { |
| 120 MutexLocker locker(&mutex_); |
| 121 ASSERT(prefix_size >= 0); |
| 122 DWORD number_of_handles = prefix_size + number_of_processes_; |
| 123 if (number_of_handles > MAXIMUM_WAIT_OBJECTS) { |
| 124 FATAL1("Only %d processes supported on Windows at this point\n", |
| 125 MAXIMUM_WAIT_OBJECTS - prefix_size); |
| 126 } |
| 127 intptr_t i = prefix_size; |
| 128 ProcessInfo* current = active_processes_; |
| 129 while (current != NULL) { |
| 130 handles[i++] = current->process_handle(); |
| 131 current = current->next(); |
| 132 } |
| 133 ASSERT(i == number_of_handles); |
| 134 // We have taken a new snapshot of the handles in the list. Reset |
| 135 // the process_added_event so we will get signaled if more |
| 136 // processes are added. |
| 137 BOOL success = ResetEvent(GetProcessAddedEvent()); |
| 138 if (!success) { |
| 139 FATAL("Failed to reset process added event"); |
| 140 } |
| 141 return number_of_handles; |
| 142 } |
| 143 |
| 144 private: |
| 145 friend class ExitCodeHandler; |
| 146 static HANDLE GetProcessAddedEvent() { |
| 147 MutexLocker locker(&process_added_event_mutex_); |
| 148 if (process_added_event_ == INVALID_HANDLE_VALUE) { |
| 149 process_added_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); |
| 150 if (process_added_event_ == NULL) { |
| 151 FATAL("Failed to allocate event for signaling addition of processes"); |
| 152 } |
| 153 } |
| 154 return process_added_event_; |
| 155 } |
| 156 // Number of processes currently in the list. |
| 157 static intptr_t number_of_processes_; |
| 158 // Linked list of ProcessInfo objects for all active processes |
| 159 // started from Dart code. |
| 160 static ProcessInfo* active_processes_; |
| 161 // Mutex protecting all accesses to the linked list of active |
| 162 // processes. |
| 163 static dart::Mutex mutex_; |
| 164 // Event used to signal that more processes have been added to the |
| 165 // list. |
| 166 static HANDLE process_added_event_; |
| 167 static dart::Mutex process_added_event_mutex_; |
| 168 }; |
| 169 |
| 170 |
| 171 intptr_t ProcessInfoList::number_of_processes_ = 0; |
| 172 ProcessInfo* ProcessInfoList::active_processes_ = NULL; |
| 173 dart::Mutex ProcessInfoList::mutex_; |
| 174 HANDLE ProcessInfoList::process_added_event_ = INVALID_HANDLE_VALUE; |
| 175 dart::Mutex ProcessInfoList::process_added_event_mutex_; |
| 176 |
| 177 |
| 178 // The exit code handler sets up a separate thread which is waiting |
| 179 // for Dart process termination and process start. When a process |
| 180 // terminates the exit code is extracted and communicated to Dart |
| 181 // through the event loop. |
| 182 class ExitCodeHandler { |
| 183 public: |
| 184 // Ensure that the ExitCodeHandler has been initialized. |
| 185 static bool EnsureInitialized() { |
| 186 // Multiple isolates could be starting processes at the same |
| 187 // time. Make sure that only one of them initializes the |
| 188 // ExitCodeHandler. |
| 189 MutexLocker locker(&mutex_); |
| 190 if (initialized_) { |
| 191 return true; |
| 192 } |
| 193 |
| 194 // Allocate an event object to be signaled when the exit code |
| 195 // thread should terminate. |
| 196 terminate_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); |
| 197 if (terminate_event_ == NULL) { |
| 198 return false; |
| 199 } |
| 200 |
| 201 // Start thread that waits for the process-addition and |
| 202 // thread-termination events as well as all process handles for |
| 203 // all active processes. |
| 204 HANDLE* events = new HANDLE[2]; |
| 205 events[0] = ProcessInfoList::GetProcessAddedEvent(); |
| 206 events[1] = terminate_event_; |
| 207 int result = dart::Thread::Start(ExitCodeHandlerEntry, |
| 208 reinterpret_cast<uword>(events)); |
| 209 if (result != 0) { |
| 210 FATAL1("Failed to start exit code handler thread: %d", result); |
| 211 } |
| 212 |
| 213 // Thread started and the ExitCodeHandler is initialized. |
| 214 initialized_ = true; |
| 215 return true; |
| 216 } |
| 217 |
| 218 static void TerminateExitCodeThread() { |
| 219 MutexLocker locker(&mutex_); |
| 220 if (!initialized_) { |
| 221 return; |
| 222 } |
| 223 |
| 224 BOOL success = SetEvent(terminate_event_); |
| 225 if (!success) { |
| 226 FATAL("Failed to set terminate event for exit code handler shutdown"); |
| 227 } |
| 228 |
| 229 { |
| 230 MonitorLocker terminate_locker(&thread_terminate_monitor_); |
| 231 while (!thread_terminated_) { |
| 232 terminate_locker.Wait(); |
| 233 } |
| 234 } |
| 235 } |
| 236 |
| 237 static void ExitCodeThreadTerminated() { |
| 238 MonitorLocker locker(&thread_terminate_monitor_); |
| 239 thread_terminated_ = true; |
| 240 locker.Notify(); |
| 241 } |
| 242 |
| 243 private: |
| 244 // Entry point for the exit code handler thread started by the |
| 245 // ExitCodeHandler. |
| 246 static void ExitCodeHandlerEntry(uword param) { |
| 247 HANDLE* events = reinterpret_cast<HANDLE*>(param); |
| 248 HANDLE wake_up_event = events[0]; |
| 249 HANDLE terminate_event = events[1]; |
| 250 delete[] events; |
| 251 |
| 252 HANDLE handles[MAXIMUM_WAIT_OBJECTS]; |
| 253 handles[0] = wake_up_event; |
| 254 handles[1] = terminate_event; |
| 255 |
| 256 while (true) { |
| 257 // Get the list of handles to wait for. Allocate a prefix of two |
| 258 // extra handles for the 'process added' and 'thread |
| 259 // termination' event objects. |
| 260 static const intptr_t kPrefixSize = 2; |
| 261 DWORD number_of_handles = |
| 262 ProcessInfoList::GetHandleArray(handles, kPrefixSize); |
| 263 ASSERT(handles[0] == wake_up_event); |
| 264 ASSERT(handles[1] == terminate_event); |
| 265 |
| 266 // Wait for the handles. |
| 267 DWORD result = |
| 268 WaitForMultipleObjects(number_of_handles, handles, FALSE, INFINITE); |
| 269 if (result == WAIT_FAILED) { |
| 270 FATAL("Failed to wait for multiple objects for exit code handling"); |
| 271 } |
| 272 |
| 273 if (result == 0) { |
| 274 // If the result is 0 the thread woke up because of process |
| 275 // addition. We don't have to do anything we just need to |
| 276 // update the list of handles we are waiting for. |
| 277 } else if (result == 1) { |
| 278 // The termination event was triggered. Free event objects and |
| 279 // exit. |
| 280 CloseHandle(terminate_event_); |
| 281 CloseHandle(wake_up_event); |
| 282 ExitCodeThreadTerminated(); |
| 283 return; |
| 64 } else { | 284 } else { |
| 65 prev->set_next(current->next()); | 285 // The result is the index of the process that was |
| 66 } | 286 // signalled. Get its exit code and communicate it to Dart. |
| 67 delete current; | 287 ASSERT(result < number_of_handles); |
| 68 return; | 288 int exit_code; |
| 69 } | 289 BOOL ok = GetExitCodeProcess(handles[result], |
| 70 prev = current; | 290 reinterpret_cast<DWORD*>(&exit_code)); |
| 71 current = current->next(); | 291 if (!ok) { |
| 72 } | 292 FATAL1("GetExitCodeProcess failed %d\n", GetLastError()); |
| 73 } | 293 } |
| 294 int negative = 0; |
| 295 if (exit_code < 0) { |
| 296 exit_code = abs(exit_code); |
| 297 negative = 1; |
| 298 } |
| 299 |
| 300 DWORD pid; |
| 301 HANDLE exit_pipe; |
| 302 bool success = ProcessInfoList::LookupProcessByHandle(handles[result], |
| 303 &pid, |
| 304 &exit_pipe); |
| 305 if (!success) { |
| 306 FATAL("Failed to lookup pid and exit pipe from process handle"); |
| 307 } |
| 308 int message[2] = { exit_code, negative }; |
| 309 DWORD written; |
| 310 ok = WriteFile(exit_pipe, message, sizeof(message), &written, NULL); |
| 311 // If the process has been closed, the read end of the exit |
| 312 // pipe has been closed. It is therefore not a problem that |
| 313 // WriteFile fails with a closed pipe error |
| 314 // (ERROR_NO_DATA). Other errors should not happen. |
| 315 if (ok && written != sizeof(message)) { |
| 316 FATAL("Failed to write entire process exit message"); |
| 317 } else if (!ok && GetLastError() != ERROR_NO_DATA) { |
| 318 FATAL1("Failed to write exit code: %d", GetLastError()); |
| 319 } |
| 320 ProcessInfoList::RemoveProcess(pid); |
| 321 } |
| 322 } |
| 323 } |
| 324 |
| 325 static dart::Mutex mutex_; |
| 326 static bool initialized_; |
| 327 static HANDLE terminate_event_; |
| 328 static bool thread_terminated_; |
| 329 static dart::Monitor thread_terminate_monitor_; |
| 330 }; |
| 331 |
| 332 |
| 333 dart::Mutex ExitCodeHandler::mutex_; |
| 334 bool ExitCodeHandler::initialized_ = false; |
| 335 HANDLE ExitCodeHandler::terminate_event_ = INVALID_HANDLE_VALUE; |
| 336 bool ExitCodeHandler::thread_terminated_ = false; |
| 337 dart::Monitor ExitCodeHandler::thread_terminate_monitor_; |
| 74 | 338 |
| 75 | 339 |
| 76 // Types of pipes to create. | 340 // Types of pipes to create. |
| 77 enum NamedPipeType { | 341 enum NamedPipeType { |
| 78 kInheritRead, | 342 kInheritRead, |
| 79 kInheritWrite, | 343 kInheritWrite, |
| 80 kInheritNone | 344 kInheritNone |
| 81 }; | 345 }; |
| 82 | 346 |
| 83 | 347 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { | 458 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { |
| 195 fprintf(stderr, "FormatMessage failed %d\n", GetLastError()); | 459 fprintf(stderr, "FormatMessage failed %d\n", GetLastError()); |
| 196 } | 460 } |
| 197 snprintf(os_error_message, os_error_message_len, "OS Error %d", error_code); | 461 snprintf(os_error_message, os_error_message_len, "OS Error %d", error_code); |
| 198 } | 462 } |
| 199 os_error_message[os_error_message_len - 1] = '\0'; | 463 os_error_message[os_error_message_len - 1] = '\0'; |
| 200 return error_code; | 464 return error_code; |
| 201 } | 465 } |
| 202 | 466 |
| 203 | 467 |
| 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, | 468 int Process::Start(const char* path, |
| 230 char* arguments[], | 469 char* arguments[], |
| 231 intptr_t arguments_length, | 470 intptr_t arguments_length, |
| 232 const char* working_directory, | 471 const char* working_directory, |
| 233 intptr_t* in, | 472 intptr_t* in, |
| 234 intptr_t* out, | 473 intptr_t* out, |
| 235 intptr_t* err, | 474 intptr_t* err, |
| 236 intptr_t* id, | 475 intptr_t* id, |
| 237 intptr_t* exit_handler, | 476 intptr_t* exit_handler, |
| 238 char* os_error_message, | 477 char* os_error_message, |
| 239 int os_error_message_len) { | 478 int os_error_message_len) { |
| 479 // Ensure that the process exit handler thread has been started. |
| 480 bool initialized = ExitCodeHandler::EnsureInitialized(); |
| 481 if (!initialized) { |
| 482 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len); |
| 483 fprintf(stderr, "Failed to initialize ExitCodeHandler: %d\n", error_code); |
| 484 return error_code; |
| 485 } |
| 486 |
| 240 HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; | 487 HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; |
| 241 HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; | 488 HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; |
| 242 HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; | 489 HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; |
| 243 HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; | 490 HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; |
| 244 | 491 |
| 245 // Generate unique pipe names for the four named pipes needed. | 492 // Generate unique pipe names for the four named pipes needed. |
| 246 char pipe_names[4][80]; | 493 char pipe_names[4][80]; |
| 247 UUID uuid; | 494 UUID uuid; |
| 248 RPC_STATUS status = UuidCreateSequential(&uuid); | 495 RPC_STATUS status = UuidCreateSequential(&uuid); |
| 249 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { | 496 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 // Deallocate command-line string. | 601 // Deallocate command-line string. |
| 355 delete[] command_line; | 602 delete[] command_line; |
| 356 | 603 |
| 357 if (result == 0) { | 604 if (result == 0) { |
| 358 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len); | 605 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len); |
| 359 CloseProcessPipes( | 606 CloseProcessPipes( |
| 360 stdin_handles, stdout_handles, stderr_handles, exit_handles); | 607 stdin_handles, stdout_handles, stderr_handles, exit_handles); |
| 361 return error_code; | 608 return error_code; |
| 362 } | 609 } |
| 363 | 610 |
| 364 ProcessInfo* process = new ProcessInfo(process_info.dwProcessId, | 611 ProcessInfoList::AddProcess(process_info.dwProcessId, |
| 365 process_info.hProcess, | 612 process_info.hProcess, |
| 366 exit_handles[kWriteHandle]); | 613 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 | 614 |
| 378 // Connect the three std streams. | 615 // Connect the three std streams. |
| 379 FileHandle* stdin_handle = new FileHandle(stdin_handles[kWriteHandle]); | 616 FileHandle* stdin_handle = new FileHandle(stdin_handles[kWriteHandle]); |
| 380 CloseHandle(stdin_handles[kReadHandle]); | 617 CloseHandle(stdin_handles[kReadHandle]); |
| 381 FileHandle* stdout_handle = new FileHandle(stdout_handles[kReadHandle]); | 618 FileHandle* stdout_handle = new FileHandle(stdout_handles[kReadHandle]); |
| 382 CloseHandle(stdout_handles[kWriteHandle]); | 619 CloseHandle(stdout_handles[kWriteHandle]); |
| 383 FileHandle* stderr_handle = new FileHandle(stderr_handles[kReadHandle]); | 620 FileHandle* stderr_handle = new FileHandle(stderr_handles[kReadHandle]); |
| 384 CloseHandle(stderr_handles[kWriteHandle]); | 621 CloseHandle(stderr_handles[kWriteHandle]); |
| 385 FileHandle* exit_handle = new FileHandle(exit_handles[kReadHandle]); | 622 FileHandle* exit_handle = new FileHandle(exit_handles[kReadHandle]); |
| 386 *in = reinterpret_cast<intptr_t>(stdout_handle); | 623 *in = reinterpret_cast<intptr_t>(stdout_handle); |
| 387 *out = reinterpret_cast<intptr_t>(stdin_handle); | 624 *out = reinterpret_cast<intptr_t>(stdin_handle); |
| 388 *err = reinterpret_cast<intptr_t>(stderr_handle); | 625 *err = reinterpret_cast<intptr_t>(stderr_handle); |
| 389 *exit_handler = reinterpret_cast<intptr_t>(exit_handle); | 626 *exit_handler = reinterpret_cast<intptr_t>(exit_handle); |
| 390 | 627 |
| 391 CloseHandle(process_info.hThread); | 628 CloseHandle(process_info.hThread); |
| 392 | 629 |
| 393 // Return process id. | 630 // Return process id. |
| 394 *id = process->pid(); | 631 *id = process_info.dwProcessId; |
| 395 return 0; | 632 return 0; |
| 396 } | 633 } |
| 397 | 634 |
| 398 | 635 |
| 399 bool Process::Kill(intptr_t id) { | 636 bool Process::Kill(intptr_t id) { |
| 400 ProcessInfo* process = LookupProcess(id); | 637 HANDLE process_handle; |
| 401 ASSERT(process != NULL); | 638 HANDLE exit_pipe; |
| 402 if (process != NULL) { | 639 bool success = |
| 403 BOOL result = TerminateProcess(process->process_handle(), -1); | 640 ProcessInfoList::LookupProcess(id, &process_handle, &exit_pipe); |
| 404 if (result == 0) { | 641 ASSERT(success); |
| 405 return false; | 642 BOOL result = TerminateProcess(process_handle, -1); |
| 406 } | 643 if (!result) { |
| 644 return false; |
| 407 } | 645 } |
| 408 return true; | 646 return true; |
| 409 } | 647 } |
| 410 | 648 |
| 411 | 649 |
| 412 void Process::Exit(intptr_t id) { | 650 void Process::TerminateExitCodeHandler() { |
| 413 RemoveProcess(id); | 651 ExitCodeHandler::TerminateExitCodeThread(); |
| 414 } | 652 } |
| 415 | |
| 416 | |
| 417 void Process::TerminateExitCodeHandler() { | |
| 418 // TODO(ager): Implement. | |
| 419 } | |
| OLD | NEW |