| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 #if !defined(DART_IO_DISABLED) | 5 #if !defined(DART_IO_DISABLED) |
| 6 | 6 |
| 7 #include "platform/globals.h" | 7 #include "platform/globals.h" |
| 8 #if defined(TARGET_OS_FUCHSIA) | 8 #if defined(TARGET_OS_FUCHSIA) |
| 9 | 9 |
| 10 #include "bin/process.h" | 10 #include "bin/process.h" |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 // ProcessInfoList. | 54 // ProcessInfoList. |
| 55 class ProcessInfo { | 55 class ProcessInfo { |
| 56 public: | 56 public: |
| 57 ProcessInfo(mx_handle_t process, intptr_t fd) | 57 ProcessInfo(mx_handle_t process, intptr_t fd) |
| 58 : process_(process), exit_pipe_fd_(fd) {} | 58 : process_(process), exit_pipe_fd_(fd) {} |
| 59 ~ProcessInfo() { | 59 ~ProcessInfo() { |
| 60 int closed = NO_RETRY_EXPECTED(close(exit_pipe_fd_)); | 60 int closed = NO_RETRY_EXPECTED(close(exit_pipe_fd_)); |
| 61 if (closed != 0) { | 61 if (closed != 0) { |
| 62 FATAL("Failed to close process exit code pipe"); | 62 FATAL("Failed to close process exit code pipe"); |
| 63 } | 63 } |
| 64 mx_handle_close(process_); |
| 64 } | 65 } |
| 65 mx_handle_t process() const { return process_; } | 66 mx_handle_t process() const { return process_; } |
| 66 intptr_t exit_pipe_fd() const { return exit_pipe_fd_; } | 67 intptr_t exit_pipe_fd() const { return exit_pipe_fd_; } |
| 67 ProcessInfo* next() const { return next_; } | 68 ProcessInfo* next() const { return next_; } |
| 68 void set_next(ProcessInfo* info) { next_ = info; } | 69 void set_next(ProcessInfo* info) { next_ = info; } |
| 69 | 70 |
| 70 private: | 71 private: |
| 71 mx_handle_t process_; | 72 mx_handle_t process_; |
| 72 intptr_t exit_pipe_fd_; | 73 intptr_t exit_pipe_fd_; |
| 73 ProcessInfo* next_; | 74 ProcessInfo* next_; |
| 74 | 75 |
| 75 DISALLOW_COPY_AND_ASSIGN(ProcessInfo); | 76 DISALLOW_COPY_AND_ASSIGN(ProcessInfo); |
| 76 }; | 77 }; |
| 77 | 78 |
| 78 | 79 |
| 79 // Singly-linked list of ProcessInfo objects for all active processes | 80 // Singly-linked list of ProcessInfo objects for all active processes |
| 80 // started from Dart. | 81 // started from Dart. |
| 81 class ProcessInfoList { | 82 class ProcessInfoList { |
| 82 public: | 83 public: |
| 83 static void AddProcess(mx_handle_t process, intptr_t fd) { | 84 static void AddProcess(mx_handle_t process, intptr_t fd) { |
| 84 MutexLocker locker(mutex_); | 85 MutexLocker locker(mutex_); |
| 85 ProcessInfo* info = new ProcessInfo(process, fd); | 86 ProcessInfo* info = new ProcessInfo(process, fd); |
| 86 info->set_next(active_processes_); | 87 info->set_next(active_processes_); |
| 87 active_processes_ = info; | 88 active_processes_ = info; |
| 88 } | 89 } |
| 89 | 90 |
| 90 | |
| 91 static intptr_t LookupProcessExitFd(mx_handle_t process) { | 91 static intptr_t LookupProcessExitFd(mx_handle_t process) { |
| 92 MutexLocker locker(mutex_); | 92 MutexLocker locker(mutex_); |
| 93 ProcessInfo* current = active_processes_; | 93 ProcessInfo* current = active_processes_; |
| 94 while (current != NULL) { | 94 while (current != NULL) { |
| 95 if (current->process() == process) { | 95 if (current->process() == process) { |
| 96 return current->exit_pipe_fd(); | 96 return current->exit_pipe_fd(); |
| 97 } | 97 } |
| 98 current = current->next(); | 98 current = current->next(); |
| 99 } | 99 } |
| 100 return 0; | 100 return 0; |
| 101 } | 101 } |
| 102 | 102 |
| 103 static bool Exists(mx_handle_t process) { |
| 104 return LookupProcessExitFd(process) != 0; |
| 105 } |
| 103 | 106 |
| 104 static void RemoveProcess(mx_handle_t process) { | 107 static void RemoveProcess(mx_handle_t process) { |
| 105 MutexLocker locker(mutex_); | 108 MutexLocker locker(mutex_); |
| 106 ProcessInfo* prev = NULL; | 109 ProcessInfo* prev = NULL; |
| 107 ProcessInfo* current = active_processes_; | 110 ProcessInfo* current = active_processes_; |
| 108 while (current != NULL) { | 111 while (current != NULL) { |
| 109 if (current->process() == process) { | 112 if (current->process() == process) { |
| 110 if (prev == NULL) { | 113 if (prev == NULL) { |
| 111 active_processes_ = current->next(); | 114 active_processes_ = current->next(); |
| 112 } else { | 115 } else { |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 mx_status_get_string(status)); | 301 mx_status_get_string(status)); |
| 299 } | 302 } |
| 300 LOG_INFO("ExitCodeHandler thread process %ld exited with %d\n", process, | 303 LOG_INFO("ExitCodeHandler thread process %ld exited with %d\n", process, |
| 301 return_code); | 304 return_code); |
| 302 | 305 |
| 303 const intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(process); | 306 const intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(process); |
| 304 LOG_INFO("ExitCodeHandler thread sending %ld code %d on fd %ld\n", process, | 307 LOG_INFO("ExitCodeHandler thread sending %ld code %d on fd %ld\n", process, |
| 305 return_code, exit_code_fd); | 308 return_code, exit_code_fd); |
| 306 if (exit_code_fd != 0) { | 309 if (exit_code_fd != 0) { |
| 307 int exit_message[2]; | 310 int exit_message[2]; |
| 308 exit_message[0] = return_code; | 311 exit_message[0] = abs(return_code); |
| 309 exit_message[1] = 0; // Do not negate return_code. | 312 exit_message[1] = return_code >= 0 ? 0 : 1; |
| 310 intptr_t result = FDUtils::WriteToBlocking(exit_code_fd, &exit_message, | 313 intptr_t result = FDUtils::WriteToBlocking(exit_code_fd, &exit_message, |
| 311 sizeof(exit_message)); | 314 sizeof(exit_message)); |
| 312 ASSERT((result == -1) || (result == sizeof(exit_code_fd))); | 315 ASSERT((result == -1) || (result == sizeof(exit_code_fd))); |
| 313 if ((result == -1) && (errno != EPIPE)) { | 316 if ((result == -1) && (errno != EPIPE)) { |
| 314 int err = errno; | 317 int err = errno; |
| 315 FATAL1("Failed to write exit code to pipe: %d\n", err); | 318 FATAL1("Failed to write exit code to pipe: %d\n", err); |
| 316 } | 319 } |
| 317 LOG_INFO("ExitCodeHandler thread wrote %ld bytes to fd %ld\n", result, | 320 LOG_INFO("ExitCodeHandler thread wrote %ld bytes to fd %ld\n", result, |
| 318 exit_code_fd); | 321 exit_code_fd); |
| 319 LOG_INFO("ExitCodeHandler thread removing process %ld from list\n", | 322 LOG_INFO("ExitCodeHandler thread removing process %ld from list\n", |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 544 DEBUG_ASSERT(err_data.IsEmpty()); | 547 DEBUG_ASSERT(err_data.IsEmpty()); |
| 545 | 548 |
| 546 // Calculate the exit code. | 549 // Calculate the exit code. |
| 547 intptr_t exit_code = exit_code_data.ints[0]; | 550 intptr_t exit_code = exit_code_data.ints[0]; |
| 548 intptr_t negative = exit_code_data.ints[1]; | 551 intptr_t negative = exit_code_data.ints[1]; |
| 549 if (negative != 0) { | 552 if (negative != 0) { |
| 550 exit_code = -exit_code; | 553 exit_code = -exit_code; |
| 551 } | 554 } |
| 552 result->set_exit_code(exit_code); | 555 result->set_exit_code(exit_code); |
| 553 | 556 |
| 557 // Close the process handle. |
| 558 mx_handle_t process = static_cast<mx_handle_t>(pid); |
| 559 mx_handle_close(process); |
| 554 return true; | 560 return true; |
| 555 } | 561 } |
| 556 | 562 |
| 557 | 563 |
| 558 bool Process::Kill(intptr_t id, int signal) { | 564 bool Process::Kill(intptr_t id, int signal) { |
| 559 errno = ENOSYS; | 565 LOG_INFO("Sending signal %d to process with id %ld\n", signal, id); |
| 560 return false; | 566 // mx_task_kill is definitely going to kill the process. |
| 567 if ((signal != SIGTERM) && (signal != SIGKILL)) { |
| 568 LOG_ERR("Signal %d not supported\n", signal); |
| 569 errno = ENOSYS; |
| 570 return false; |
| 571 } |
| 572 // We can only use mx_task_kill if we know id is a process handle, and we only |
| 573 // know that for sure if it's in our list. |
| 574 mx_handle_t process = static_cast<mx_handle_t>(id); |
| 575 if (!ProcessInfoList::Exists(process)) { |
| 576 LOG_ERR("Process %ld wasn't in the ProcessInfoList\n", id); |
| 577 errno = ESRCH; // No such process. |
| 578 return false; |
| 579 } |
| 580 mx_status_t status = mx_task_kill(process); |
| 581 if (status != NO_ERROR) { |
| 582 LOG_ERR("mx_task_kill failed: %s\n", mx_status_get_string(status)); |
| 583 errno = EPERM; // TODO(zra): Figure out what it really should be. |
| 584 return false; |
| 585 } |
| 586 LOG_INFO("Signal %d sent successfully to process %ld\n", signal, id); |
| 587 return true; |
| 561 } | 588 } |
| 562 | 589 |
| 563 | 590 |
| 564 class ProcessStarter { | 591 class ProcessStarter { |
| 565 public: | 592 public: |
| 566 ProcessStarter(const char* path, | 593 ProcessStarter(const char* path, |
| 567 char* arguments[], | 594 char* arguments[], |
| 568 intptr_t arguments_length, | 595 intptr_t arguments_length, |
| 569 const char* working_directory, | 596 const char* working_directory, |
| 570 char* environment[], | 597 char* environment[], |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 void Process::ClearSignalHandler(intptr_t signal) { | 839 void Process::ClearSignalHandler(intptr_t signal) { |
| 813 UNIMPLEMENTED(); | 840 UNIMPLEMENTED(); |
| 814 } | 841 } |
| 815 | 842 |
| 816 } // namespace bin | 843 } // namespace bin |
| 817 } // namespace dart | 844 } // namespace dart |
| 818 | 845 |
| 819 #endif // defined(TARGET_OS_FUCHSIA) | 846 #endif // defined(TARGET_OS_FUCHSIA) |
| 820 | 847 |
| 821 #endif // !defined(DART_IO_DISABLED) | 848 #endif // !defined(DART_IO_DISABLED) |
| OLD | NEW |