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 |