Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4934)

Unified Diff: runtime/bin/process_macos.cc

Issue 119093007: Signal handling, take 2. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/bin/process_linux.cc ('k') | runtime/bin/process_patch.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/process_macos.cc
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index edb222af3fb11acc7037a1f9a813ba374529ea63..ae0f37e749462c0aba80502078bb43b03eb8b5d8 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -18,6 +18,7 @@
#include "bin/fdutils.h"
#include "bin/log.h"
+#include "bin/signal_blocker.h"
#include "bin/thread.h"
extern char **environ;
@@ -622,8 +623,44 @@ bool Process::Wait(intptr_t pid,
}
+static int SignalMap(intptr_t id) {
+ switch (static_cast<ProcessSignals>(id)) {
+ case kSighup: return SIGHUP;
+ case kSigint: return SIGINT;
+ case kSigquit: return SIGQUIT;
+ case kSigill: return SIGILL;
+ case kSigtrap: return SIGTRAP;
+ case kSigabrt: return SIGABRT;
+ case kSigbus: return SIGBUS;
+ case kSigfpe: return SIGFPE;
+ case kSigkill: return SIGKILL;
+ case kSigusr1: return SIGUSR1;
+ case kSigsegv: return SIGSEGV;
+ case kSigusr2: return SIGUSR2;
+ case kSigpipe: return SIGPIPE;
+ case kSigalrm: return SIGALRM;
+ case kSigterm: return SIGTERM;
+ case kSigchld: return SIGCHLD;
+ case kSigcont: return SIGCONT;
+ case kSigstop: return SIGSTOP;
+ case kSigtstp: return SIGTSTP;
+ case kSigttin: return SIGTTIN;
+ case kSigttou: return SIGTTOU;
+ case kSigurg: return SIGURG;
+ case kSigxcpu: return SIGXCPU;
+ case kSigxfsz: return SIGXFSZ;
+ case kSigvtalrm: return SIGVTALRM;
+ case kSigprof: return SIGPROF;
+ case kSigwinch: return SIGWINCH;
+ case kSigpoll: return -1;
+ case kSigsys: return SIGSYS;
+ }
+ return -1;
+}
+
+
bool Process::Kill(intptr_t id, int signal) {
- return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1);
+ return (TEMP_FAILURE_RETRY(kill(id, SignalMap(signal))) != -1);
}
@@ -636,6 +673,119 @@ 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) {
+ signal = SignalMap(signal);
+ if (signal == -1) return -1;
+ 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) {
+ signal = SignalMap(signal);
+ if (signal == -1) return;
+ 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
« no previous file with comments | « runtime/bin/process_linux.cc ('k') | runtime/bin/process_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698