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

Unified Diff: remoting/host/posix/signal_handler.cc

Issue 10905081: Pass Me2Me config via stdin. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed #include guard footer. Created 8 years, 3 months 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
Index: remoting/host/posix/signal_handler.cc
diff --git a/remoting/host/posix/signal_handler.cc b/remoting/host/posix/signal_handler.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b10e3992a01480317572d478bd7f884addb537bf
--- /dev/null
+++ b/remoting/host/posix/signal_handler.cc
@@ -0,0 +1,112 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(jamiewalch): Add unit tests for this.
+
+#include "remoting/host/posix/signal_handler.h"
+
+#include <errno.h>
+#include <signal.h>
+
+#include <list>
+#include <utility>
+
+#include "base/compiler_specific.h"
+#include "base/eintr_wrapper.h"
+#include "base/message_loop.h"
+#include "base/message_pump_libevent.h"
+#include "base/threading/platform_thread.h"
+
+namespace remoting {
+namespace {
+
+class SignalListener : public base::MessagePumpLibevent::Watcher {
+ public:
+ SignalListener();
+
+ void AddSignalHandler(int signal, const SignalHandler& handler);
+
+ virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
+ virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {}
+
+ // WatchFileDescriptor needs a controller through which the operation can be
+ // canceled. We don't use it, but this is as good a place as any to store it.
+ base::MessagePumpLibevent::FileDescriptorWatcher controller;
+
+ private:
+ typedef std::pair<int, SignalHandler> SignalAndHandler;
+ typedef std::list<SignalAndHandler> SignalHandlers;
+ SignalHandlers signal_handlers_;
+};
+
+SignalListener::SignalListener() {
+}
+
+void SignalListener::AddSignalHandler(int signal,
+ const SignalHandler& handler) {
+ signal_handlers_.push_back(SignalAndHandler(signal, handler));
+}
+
+void SignalListener::OnFileCanReadWithoutBlocking(int fd) {
+ char buffer;
+ int result = HANDLE_EINTR(read(fd, &buffer, sizeof(buffer)));
+ if (result > 0) {
+ for (SignalHandlers::const_iterator i = signal_handlers_.begin();
+ i != signal_handlers_.end();
+ ++i) {
+ if (i->first == buffer) {
+ i->second.Run(i->first);
+ }
+ }
+ }
+}
+
+SignalListener* g_signal_listener = NULL;
+int g_write_fd = 0;
+
+void GlobalSignalHandler(int signal) {
+ char byte = signal;
+ int r ALLOW_UNUSED = write(g_write_fd, &byte, 1);
+}
+
+} // namespace
+
+// RegisterSignalHandler registers a signal handler that writes a byte to a
+// pipe each time a signal is received. The read end of the pipe is registered
+// with the current MessageLoop (which must be of type IO); whenever the pipe
+// is readable, it invokes the specified callback.
+//
+// This arrangement is required because the set of system APIs that are safe to
+// call from a signal handler is very limited (but does include write).
+bool RegisterSignalHandler(int signum, const SignalHandler& handler) {
Lambros 2012/09/06 00:47:19 nit: signal or signal_number ?
Jamie 2012/09/06 17:31:01 Done.
+ CHECK(signum < 256); // Don't want to worry about multi-byte writes.
+ if (!g_signal_listener) {
+ g_signal_listener = new SignalListener();
+ MessageLoopForIO* message_loop = MessageLoopForIO::current();
+ int pipefd[2];
Lambros 2012/09/06 00:47:19 nit: pipe_fd seems better ?
Jamie 2012/09/06 17:31:01 Done.
+ int result = pipe(pipefd);
+ if (result < 0) {
+ LOG(ERROR) << "Could not create signal pipe: " << errno;
+ return false;
+ }
+ g_write_fd = pipefd[1];
+ result = message_loop->WatchFileDescriptor(
+ pipefd[0], true, MessageLoopForIO::WATCH_READ,
+ &g_signal_listener->controller, g_signal_listener);
+ if (!result) {
+ delete g_signal_listener;
+ g_signal_listener = NULL;
+ LOG(ERROR) << "Failed to create signal detector task.";
+ return false;
+ }
+ }
+ if (signal(signum, GlobalSignalHandler) == SIG_ERR) {
+ LOG(ERROR) << "signal() failed: " << errno;
+ return false;
+ }
+ g_signal_listener->AddSignalHandler(signum, handler);
+ return true;
+}
+
+} // namespace remoting

Powered by Google App Engine
This is Rietveld 408576698