Chromium Code Reviews| Index: runtime/bin/process_linux.cc |
| diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc |
| index 95d11cdce7dc2b8ee6a2aaf0ce1bcf12900d69de..02546987011b491e9329b9af650741706957146a 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,116 @@ intptr_t Process::CurrentProcessId() { |
| return static_cast<intptr_t>(getpid()); |
| } |
| + |
| +static Mutex* signal_mutex = new Mutex(); |
| +static const int kSignalsCount = 3; |
| +static const int kSignals[kSignalsCount] = { |
| + SIGINT, |
| + SIGWINCH, |
| + SIGTERM |
|
Søren Gjesse
2013/12/18 08:07:14
Shouldn't the SIGUSR1 and SIGUSR2 be in this list
Anders Johnsen
2013/12/18 21:20:29
Done.
|
| +}; |
| + |
| + |
| +class SignalInfo { |
| + public: |
| + SignalInfo(int fd, SignalInfo* prev = NULL) |
| + : fd_(fd), port_(Dart_GetMainPortId()), next_(NULL), prev_(prev) { |
| + if (prev_ != NULL) { |
| + prev_->next_ = this; |
| + } |
| + } |
| + |
| + void Unlink() { |
| + if (prev_ != NULL) { |
| + prev_->next_ = next_; |
| + } |
| + if (next_ != NULL) { |
| + next_->prev_ = prev_; |
| + } |
| + } |
| + |
| + int fd() const { return fd_; } |
| + Dart_Port port() const { return port_; } |
| + SignalInfo* next() const { return next_; } |
| + |
| + private: |
| + int fd_; |
| + Dart_Port port_; |
| + SignalInfo* next_; |
| + SignalInfo* prev_; |
| +}; |
| + |
| + |
| +static SignalInfo* signal_handlers[32] = { NULL }; |
|
Søren Gjesse
2013/12/18 08:07:14
Wouldn't it be OK to have the signal in the Signal
Anders Johnsen
2013/12/18 21:20:29
Done.
|
| + |
| + |
| +static void SignalHandler(int signal) { |
| + MutexLocker lock(signal_mutex); |
| + const SignalInfo* handler = signal_handlers[signal]; |
| + while (handler != NULL) { |
| + int value = 0; |
|
Søren Gjesse
2013/12/18 08:07:14
Can we loose a signal here if the non-blocking wri
Anders Johnsen
2013/12/18 21:20:29
This write is blocking.
|
| + VOID_TEMP_FAILURE_RETRY(write(handler->fd(), &value, 1)); |
| + handler = handler->next(); |
| + } |
| +} |
| + |
| + |
| +intptr_t Process::SetSignalHandler(intptr_t signal) { |
|
Søren Gjesse
2013/12/18 08:07:14
Check that the signal is actually in the kSignals
Anders Johnsen
2013/12/18 21:20:29
Done.
|
| + 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); |
| + if (signal_handlers[signal] == NULL) { |
| + 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; |
| + } |
| + SignalInfo* info = new SignalInfo(fds[1]); |
| + signal_handlers[signal] = info; |
| + } else { |
| + new SignalInfo(fds[1], signal_handlers[signal]); |
| + } |
| + return fds[0]; |
| +} |
| + |
| + |
| +void Process::ClearSignalHandler(intptr_t signal) { |
| + ThreadSignalBlocker blocker(kSignalsCount, kSignals); |
| + MutexLocker lock(signal_mutex); |
| + SignalInfo * handler = signal_handlers[signal]; |
| + while (handler != NULL) { |
|
Søren Gjesse
2013/12/18 08:07:14
Why this loop? Seems that port is always equals to
Anders Johnsen
2013/12/18 21:20:29
This is a way to map it to different isolates. We
|
| + if (handler->port() == Dart_GetMainPortId()) { |
| + handler->Unlink(); |
| + break; |
| + } |
| + } |
| + if (handler != NULL) { |
| + if (signal_handlers[signal] == handler) { |
| + signal_handlers[signal] = handler->next(); |
| + } |
| + if (signal_handlers[signal] == NULL) { |
| + struct sigaction act; |
| + bzero(&act, sizeof(act)); |
| + act.sa_handler = SIG_DFL; |
| + VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(sigaction(signal, &act, NULL)); |
| + } |
| + } |
| + delete handler; |
| +} |
| + |
| } // namespace bin |
| } // namespace dart |