Chromium Code Reviews| 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 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 Loading... | |
| 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 Loading... | |
| 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 } | |
| OLD | NEW |