| Index: runtime/bin/process_linux.cc
|
| diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
|
| index 95d11cdce7dc2b8ee6a2aaf0ce1bcf12900d69de..7479064013cf16f2e203bc36149b248d2ae52561 100644
|
| --- a/runtime/bin/process_linux.cc
|
| +++ b/runtime/bin/process_linux.cc
|
| @@ -18,6 +18,7 @@
|
|
|
| #include "bin/fdutils.h"
|
| #include "bin/log.h"
|
| +#include "bin/signal_blocker.h"
|
| #include "bin/thread.h"
|
|
|
|
|
| @@ -630,6 +631,115 @@ intptr_t Process::CurrentProcessId() {
|
| return static_cast<intptr_t>(getpid());
|
| }
|
|
|
| +
|
| +static Mutex* signal_mutex = new Mutex();
|
| +static SignalInfo* signal_handlers = NULL;
|
| +static const int kSignalsCount = 5;
|
| +static const int kSignals[kSignalsCount] = {
|
| + SIGINT,
|
| + SIGWINCH,
|
| + SIGTERM,
|
| + SIGUSR1,
|
| + SIGUSR2
|
| +};
|
| +
|
| +
|
| +SignalInfo::~SignalInfo() {
|
| + VOID_TEMP_FAILURE_RETRY(close(fd_));
|
| +}
|
| +
|
| +
|
| +static void SignalHandler(int signal) {
|
| + MutexLocker lock(signal_mutex);
|
| + const SignalInfo* handler = signal_handlers;
|
| + while (handler != NULL) {
|
| + if (handler->signal() == signal) {
|
| + int value = 0;
|
| + VOID_TEMP_FAILURE_RETRY(write(handler->fd(), &value, 1));
|
| + }
|
| + handler = handler->next();
|
| + }
|
| +}
|
| +
|
| +
|
| +intptr_t Process::SetSignalHandler(intptr_t signal) {
|
| + bool found = false;
|
| + for (int i = 0; i < kSignalsCount; i++) {
|
| + if (kSignals[i] == signal) {
|
| + found = true;
|
| + break;
|
| + }
|
| + }
|
| + if (!found) return -1;
|
| + int fds[2];
|
| + if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(pipe(fds)) != 0) {
|
| + return -1;
|
| + }
|
| + if (!FDUtils::SetNonBlocking(fds[0])) {
|
| + VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[0]));
|
| + VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[1]));
|
| + return -1;
|
| + }
|
| + ThreadSignalBlocker blocker(kSignalsCount, kSignals);
|
| + MutexLocker lock(signal_mutex);
|
| + SignalInfo* handler = signal_handlers;
|
| + bool listen = true;
|
| + while (handler != NULL) {
|
| + if (handler->signal() == signal) {
|
| + listen = false;
|
| + break;
|
| + }
|
| + handler = handler->next();
|
| + }
|
| + if (listen) {
|
| + struct sigaction act;
|
| + bzero(&act, sizeof(act));
|
| + act.sa_handler = SignalHandler;
|
| + int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
|
| + sigaction(signal, &act, NULL));
|
| + if (status < 0) {
|
| + VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[0]));
|
| + VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[1]));
|
| + return -1;
|
| + }
|
| + }
|
| + if (signal_handlers == NULL) {
|
| + signal_handlers = new SignalInfo(fds[1], signal);
|
| + } else {
|
| + new SignalInfo(fds[1], signal, signal_handlers);
|
| + }
|
| + return fds[0];
|
| +}
|
| +
|
| +
|
| +void Process::ClearSignalHandler(intptr_t signal) {
|
| + ThreadSignalBlocker blocker(kSignalsCount, kSignals);
|
| + MutexLocker lock(signal_mutex);
|
| + SignalInfo* handler = signal_handlers;
|
| + bool unlisten = true;
|
| + while (handler != NULL) {
|
| + bool remove = false;
|
| + if (handler->signal() == signal) {
|
| + if (handler->port() == Dart_GetMainPortId()) {
|
| + if (signal_handlers == handler) signal_handlers = handler->next();
|
| + handler->Unlink();
|
| + remove = true;
|
| + } else {
|
| + unlisten = false;
|
| + }
|
| + }
|
| + SignalInfo* next = handler->next();
|
| + if (remove) delete handler;
|
| + handler = next;
|
| + }
|
| + if (unlisten) {
|
| + struct sigaction act;
|
| + bzero(&act, sizeof(act));
|
| + act.sa_handler = SIG_DFL;
|
| + VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(sigaction(signal, &act, NULL));
|
| + }
|
| +}
|
| +
|
| } // namespace bin
|
| } // namespace dart
|
|
|
|
|