| 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 "bin/thread.h" |
| 11 #include "platform/globals.h" | 11 #include "platform/globals.h" |
| 12 | 12 |
| 13 static const int kReadHandle = 0; | 13 static const int kReadHandle = 0; |
| 14 static const int kWriteHandle = 1; | 14 static const int kWriteHandle = 1; |
| 15 | 15 |
| 16 | 16 |
| 17 // ProcessInfo is used to map a process id to the process handle and | 17 // ProcessInfo is used to map a process id to the process handle, |
| 18 // the pipe used to communicate the exit code of the process to Dart. | 18 // wait handle for registered exit code event and the pipe used to |
| 19 // communicate the exit code of the process to Dart. |
| 19 // ProcessInfo objects are kept in the static singly-linked | 20 // ProcessInfo objects are kept in the static singly-linked |
| 20 // ProcessInfoList. | 21 // ProcessInfoList. |
| 21 class ProcessInfo { | 22 class ProcessInfo { |
| 22 public: | 23 public: |
| 23 ProcessInfo(DWORD process_id, HANDLE process_handle, HANDLE exit_pipe) | 24 ProcessInfo(DWORD process_id, |
| 25 HANDLE process_handle, |
| 26 HANDLE wait_handle, |
| 27 HANDLE exit_pipe) |
| 24 : process_id_(process_id), | 28 : process_id_(process_id), |
| 25 process_handle_(process_handle), | 29 process_handle_(process_handle), |
| 30 wait_handle_(wait_handle), |
| 26 exit_pipe_(exit_pipe) { } | 31 exit_pipe_(exit_pipe) { } |
| 27 | 32 |
| 28 ~ProcessInfo() { | 33 ~ProcessInfo() { |
| 29 BOOL success = CloseHandle(process_handle_); | 34 BOOL success = CloseHandle(process_handle_); |
| 30 if (!success) { | 35 if (!success) { |
| 31 FATAL("Failed to close process handle"); | 36 FATAL("Failed to close process handle"); |
| 32 } | 37 } |
| 33 success = CloseHandle(exit_pipe_); | 38 success = CloseHandle(exit_pipe_); |
| 34 if (!success) { | 39 if (!success) { |
| 35 FATAL("Failed to close process exit code pipe"); | 40 FATAL("Failed to close process exit code pipe"); |
| 36 } | 41 } |
| 37 } | 42 } |
| 38 | 43 |
| 39 DWORD pid() { return process_id_; } | 44 DWORD pid() { return process_id_; } |
| 40 HANDLE process_handle() { return process_handle_; } | 45 HANDLE process_handle() { return process_handle_; } |
| 46 HANDLE wait_handle() { return wait_handle_; } |
| 41 HANDLE exit_pipe() { return exit_pipe_; } | 47 HANDLE exit_pipe() { return exit_pipe_; } |
| 42 ProcessInfo* next() { return next_; } | 48 ProcessInfo* next() { return next_; } |
| 43 void set_next(ProcessInfo* next) { next_ = next; } | 49 void set_next(ProcessInfo* next) { next_ = next; } |
| 44 | 50 |
| 45 private: | 51 private: |
| 46 DWORD process_id_; // Process id. | 52 // Process id. |
| 47 HANDLE process_handle_; // Process handle. | 53 DWORD process_id_; |
| 48 HANDLE exit_pipe_; // File descriptor for pipe to report exit code. | 54 // Process handle. |
| 55 HANDLE process_handle_; |
| 56 // Wait handle identifying the exit-code wait operation registered |
| 57 // with RegisterWaitForSingleObject. |
| 58 HANDLE wait_handle_; |
| 59 // File descriptor for pipe to report exit code. |
| 60 HANDLE exit_pipe_; |
| 61 // Link to next ProcessInfo object in the singly-linked list. |
| 49 ProcessInfo* next_; | 62 ProcessInfo* next_; |
| 50 }; | 63 }; |
| 51 | 64 |
| 52 | 65 |
| 53 // Singly-linked list of ProcessInfo objects for all active processes | 66 // Singly-linked list of ProcessInfo objects for all active processes |
| 54 // started from Dart. | 67 // started from Dart. |
| 55 class ProcessInfoList { | 68 class ProcessInfoList { |
| 56 public: | 69 public: |
| 57 static void AddProcess(DWORD pid, HANDLE handle, HANDLE pipe) { | 70 static void AddProcess(DWORD pid, HANDLE handle, HANDLE pipe) { |
| 71 // Create a wait operation for the process handle to extract |
| 72 // the exit code. |
| 73 HANDLE wait_handle = INVALID_HANDLE_VALUE; |
| 74 BOOL success = RegisterWaitForSingleObject( |
| 75 &wait_handle, |
| 76 handle, |
| 77 reinterpret_cast<WAITORTIMERCALLBACK>(ExitCodeCallback), |
| 78 reinterpret_cast<void*>(pid), |
| 79 INFINITE, |
| 80 WT_EXECUTEONLYONCE); |
| 81 if (!success) { |
| 82 FATAL("Failed to register exit code wait operation."); |
| 83 } |
| 84 ProcessInfo* info = new ProcessInfo(pid, handle, wait_handle, pipe); |
| 85 // Now mutate the process list under the mutex. |
| 58 MutexLocker locker(&mutex_); | 86 MutexLocker locker(&mutex_); |
| 59 ProcessInfo* info = new ProcessInfo(pid, handle, pipe); | |
| 60 info->set_next(active_processes_); | 87 info->set_next(active_processes_); |
| 61 active_processes_ = info; | 88 active_processes_ = info; |
| 62 ++number_of_processes_; | |
| 63 BOOL success = SetEvent(GetProcessAddedEvent()); | |
| 64 if (!success) { | |
| 65 FATAL("Failed to set process added event"); | |
| 66 } | |
| 67 } | 89 } |
| 68 | 90 |
| 69 static bool LookupProcess(DWORD pid, HANDLE* handle, HANDLE* pipe) { | 91 static bool LookupProcess(DWORD pid, |
| 92 HANDLE* handle, |
| 93 HANDLE* wait_handle, |
| 94 HANDLE* pipe) { |
| 70 MutexLocker locker(&mutex_); | 95 MutexLocker locker(&mutex_); |
| 71 ProcessInfo* current = active_processes_; | 96 ProcessInfo* current = active_processes_; |
| 72 while (current != NULL) { | 97 while (current != NULL) { |
| 73 if (current->pid() == pid) { | 98 if (current->pid() == pid) { |
| 74 *handle = current->process_handle(); | 99 *handle = current->process_handle(); |
| 100 *wait_handle = current->wait_handle(); |
| 75 *pipe = current->exit_pipe(); | 101 *pipe = current->exit_pipe(); |
| 76 return true; | 102 return true; |
| 77 } | 103 } |
| 78 current = current->next(); | |
| 79 } | |
| 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(); | 104 current = current->next(); |
| 93 } | 105 } |
| 94 return false; | 106 return false; |
| 95 } | 107 } |
| 96 | 108 |
| 97 static void RemoveProcess(DWORD pid) { | 109 static void RemoveProcess(DWORD pid) { |
| 98 MutexLocker locker(&mutex_); | 110 MutexLocker locker(&mutex_); |
| 99 ProcessInfo* prev = NULL; | 111 ProcessInfo* prev = NULL; |
| 100 ProcessInfo* current = active_processes_; | 112 ProcessInfo* current = active_processes_; |
| 101 while (current != NULL) { | 113 while (current != NULL) { |
| 102 if (current->pid() == pid) { | 114 if (current->pid() == pid) { |
| 103 if (prev == NULL) { | 115 if (prev == NULL) { |
| 104 active_processes_ = current->next(); | 116 active_processes_ = current->next(); |
| 105 } else { | 117 } else { |
| 106 prev->set_next(current->next()); | 118 prev->set_next(current->next()); |
| 107 } | 119 } |
| 108 delete current; | 120 delete current; |
| 109 --number_of_processes_; | |
| 110 return; | 121 return; |
| 111 } | 122 } |
| 112 prev = current; | 123 prev = current; |
| 113 current = current->next(); | 124 current = current->next(); |
| 114 } | 125 } |
| 115 } | 126 } |
| 116 | 127 |
| 117 // Extract the process handles from the process list. The handles | 128 private: |
| 118 // array argument must have space for MAXIMUM_WAIT_OBJECTS handles. | 129 // Callback called when an exit code is available from one of the |
| 119 static DWORD GetHandleArray(HANDLE* handles, intptr_t prefix_size) { | 130 // processes in the list. |
| 120 MutexLocker locker(&mutex_); | 131 static void ExitCodeCallback(void* data, bool timed_out) { |
| 121 ASSERT(prefix_size >= 0); | 132 if (timed_out) return; |
| 122 DWORD number_of_handles = prefix_size + number_of_processes_; | 133 DWORD pid = reinterpret_cast<DWORD>(data); |
| 123 if (number_of_handles > MAXIMUM_WAIT_OBJECTS) { | 134 HANDLE handle; |
| 124 FATAL1("Only %d processes supported on Windows at this point\n", | 135 HANDLE wait_handle; |
| 125 MAXIMUM_WAIT_OBJECTS - prefix_size); | 136 HANDLE exit_pipe; |
| 137 bool success = LookupProcess(pid, &handle, &wait_handle, &exit_pipe); |
| 138 if (!success) { |
| 139 FATAL("Failed to lookup process in list of active processes"); |
| 126 } | 140 } |
| 127 intptr_t i = prefix_size; | 141 // Unregister the event in a non-blocking way. |
| 128 ProcessInfo* current = active_processes_; | 142 BOOL ok = UnregisterWait(wait_handle); |
| 129 while (current != NULL) { | 143 if (!ok && GetLastError() != ERROR_IO_PENDING) { |
| 130 handles[i++] = current->process_handle(); | 144 FATAL("Failed unregistering wait operation"); |
| 131 current = current->next(); | |
| 132 } | 145 } |
| 133 ASSERT(i == number_of_handles); | 146 // Get and report the exit code to Dart. |
| 134 // We have taken a new snapshot of the handles in the list. Reset | 147 int exit_code; |
| 135 // the process_added_event so we will get signaled if more | 148 ok = GetExitCodeProcess(handle, |
| 136 // processes are added. | 149 reinterpret_cast<DWORD*>(&exit_code)); |
| 137 BOOL success = ResetEvent(GetProcessAddedEvent()); | 150 if (!ok) { |
| 138 if (!success) { | 151 FATAL1("GetExitCodeProcess failed %d\n", GetLastError()); |
| 139 FATAL("Failed to reset process added event"); | |
| 140 } | 152 } |
| 141 return number_of_handles; | 153 int negative = 0; |
| 154 if (exit_code < 0) { |
| 155 exit_code = abs(exit_code); |
| 156 negative = 1; |
| 157 } |
| 158 int message[2] = { exit_code, negative }; |
| 159 DWORD written; |
| 160 ok = WriteFile(exit_pipe, message, sizeof(message), &written, NULL); |
| 161 // If the process has been closed, the read end of the exit |
| 162 // pipe has been closed. It is therefore not a problem that |
| 163 // WriteFile fails with a closed pipe error |
| 164 // (ERROR_NO_DATA). Other errors should not happen. |
| 165 if (ok && written != sizeof(message)) { |
| 166 FATAL("Failed to write entire process exit message"); |
| 167 } else if (!ok && GetLastError() != ERROR_NO_DATA) { |
| 168 FATAL1("Failed to write exit code: %d", GetLastError()); |
| 169 } |
| 170 // Remove the process from the list of active processes. |
| 171 RemoveProcess(pid); |
| 142 } | 172 } |
| 143 | 173 |
| 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 | 174 // Linked list of ProcessInfo objects for all active processes |
| 159 // started from Dart code. | 175 // started from Dart code. |
| 160 static ProcessInfo* active_processes_; | 176 static ProcessInfo* active_processes_; |
| 161 // Mutex protecting all accesses to the linked list of active | 177 // Mutex protecting all accesses to the linked list of active |
| 162 // processes. | 178 // processes. |
| 163 static dart::Mutex mutex_; | 179 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 }; | 180 }; |
| 169 | 181 |
| 170 | 182 |
| 171 intptr_t ProcessInfoList::number_of_processes_ = 0; | |
| 172 ProcessInfo* ProcessInfoList::active_processes_ = NULL; | 183 ProcessInfo* ProcessInfoList::active_processes_ = NULL; |
| 173 dart::Mutex ProcessInfoList::mutex_; | 184 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; | |
| 284 } else { | |
| 285 // The result is the index of the process that was | |
| 286 // signalled. Get its exit code and communicate it to Dart. | |
| 287 ASSERT(result < number_of_handles); | |
| 288 int exit_code; | |
| 289 BOOL ok = GetExitCodeProcess(handles[result], | |
| 290 reinterpret_cast<DWORD*>(&exit_code)); | |
| 291 if (!ok) { | |
| 292 FATAL1("GetExitCodeProcess failed %d\n", GetLastError()); | |
| 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_; | |
| 338 | 185 |
| 339 | 186 |
| 340 // Types of pipes to create. | 187 // Types of pipes to create. |
| 341 enum NamedPipeType { | 188 enum NamedPipeType { |
| 342 kInheritRead, | 189 kInheritRead, |
| 343 kInheritWrite, | 190 kInheritWrite, |
| 344 kInheritNone | 191 kInheritNone |
| 345 }; | 192 }; |
| 346 | 193 |
| 347 | 194 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 const char* working_directory, | 318 const char* working_directory, |
| 472 char* environment[], | 319 char* environment[], |
| 473 intptr_t environment_length, | 320 intptr_t environment_length, |
| 474 intptr_t* in, | 321 intptr_t* in, |
| 475 intptr_t* out, | 322 intptr_t* out, |
| 476 intptr_t* err, | 323 intptr_t* err, |
| 477 intptr_t* id, | 324 intptr_t* id, |
| 478 intptr_t* exit_handler, | 325 intptr_t* exit_handler, |
| 479 char* os_error_message, | 326 char* os_error_message, |
| 480 int os_error_message_len) { | 327 int os_error_message_len) { |
| 481 // Ensure that the process exit handler thread has been started. | |
| 482 bool initialized = ExitCodeHandler::EnsureInitialized(); | |
| 483 if (!initialized) { | |
| 484 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len); | |
| 485 fprintf(stderr, "Failed to initialize ExitCodeHandler: %d\n", error_code); | |
| 486 return error_code; | |
| 487 } | |
| 488 | |
| 489 HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; | 328 HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; |
| 490 HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; | 329 HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; |
| 491 HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; | 330 HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; |
| 492 HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; | 331 HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; |
| 493 | 332 |
| 494 // Generate unique pipe names for the four named pipes needed. | 333 // Generate unique pipe names for the four named pipes needed. |
| 495 char pipe_names[4][80]; | 334 char pipe_names[4][80]; |
| 496 UUID uuid; | 335 UUID uuid; |
| 497 RPC_STATUS status = UuidCreateSequential(&uuid); | 336 RPC_STATUS status = UuidCreateSequential(&uuid); |
| 498 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { | 337 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 CloseHandle(process_info.hThread); | 495 CloseHandle(process_info.hThread); |
| 657 | 496 |
| 658 // Return process id. | 497 // Return process id. |
| 659 *id = process_info.dwProcessId; | 498 *id = process_info.dwProcessId; |
| 660 return 0; | 499 return 0; |
| 661 } | 500 } |
| 662 | 501 |
| 663 | 502 |
| 664 bool Process::Kill(intptr_t id) { | 503 bool Process::Kill(intptr_t id) { |
| 665 HANDLE process_handle; | 504 HANDLE process_handle; |
| 505 HANDLE wait_handle; |
| 666 HANDLE exit_pipe; | 506 HANDLE exit_pipe; |
| 667 bool success = | 507 bool success = ProcessInfoList::LookupProcess(id, |
| 668 ProcessInfoList::LookupProcess(id, &process_handle, &exit_pipe); | 508 &process_handle, |
| 509 &wait_handle, |
| 510 &exit_pipe); |
| 669 ASSERT(success); | 511 ASSERT(success); |
| 670 BOOL result = TerminateProcess(process_handle, -1); | 512 BOOL result = TerminateProcess(process_handle, -1); |
| 671 if (!result) { | 513 if (!result) { |
| 672 return false; | 514 return false; |
| 673 } | 515 } |
| 674 return true; | 516 return true; |
| 675 } | 517 } |
| 676 | 518 |
| 677 | 519 |
| 678 void Process::TerminateExitCodeHandler() { | 520 void Process::TerminateExitCodeHandler() { |
| 679 ExitCodeHandler::TerminateExitCodeThread(); | 521 // Nothing needs to be done on Windows. |
| 680 } | 522 } |
| 523 |
| OLD | NEW |