diff options
author | jamiewalch@chromium.org <jamiewalch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-07 05:28:50 +0000 |
---|---|---|
committer | jamiewalch@chromium.org <jamiewalch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-07 05:28:50 +0000 |
commit | 447f76fe760ec8cb53f059c9fee1e18ef1ed15fc (patch) | |
tree | 3e19b0d1dec560b148d0fb6193f4b7d34bcc7a3b /remoting/host/posix | |
parent | 3392da30a3cc57f524f58382c5d60e45da851163 (diff) | |
download | chromium_src-447f76fe760ec8cb53f059c9fee1e18ef1ed15fc.zip chromium_src-447f76fe760ec8cb53f059c9fee1e18ef1ed15fc.tar.gz chromium_src-447f76fe760ec8cb53f059c9fee1e18ef1ed15fc.tar.bz2 |
Pass Me2Me config via stdin.
This allows the host to restart even if the config file is no longer readable (for example, if it is on an NFS share). One downside is that the host can no longer re-read its configuration without restarting.
I ended up implementing a SIGTERM handler to provide clean shutdown. It's easily extractable into a separate CL; let me know if you'd like me to do that.
BUG=None
Review URL: https://chromiumcodereview.appspot.com/10905081
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@155314 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/host/posix')
-rw-r--r-- | remoting/host/posix/sighup_listener.cc | 94 | ||||
-rw-r--r-- | remoting/host/posix/signal_handler.cc | 114 | ||||
-rw-r--r-- | remoting/host/posix/signal_handler.h (renamed from remoting/host/posix/sighup_listener.h) | 15 |
3 files changed, 123 insertions, 100 deletions
diff --git a/remoting/host/posix/sighup_listener.cc b/remoting/host/posix/sighup_listener.cc deleted file mode 100644 index 5a4ad07..0000000 --- a/remoting/host/posix/sighup_listener.cc +++ /dev/null @@ -1,94 +0,0 @@ -// 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/sighup_listener.h" - -#include <errno.h> -#include <signal.h> - -#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 { - -class SigHupListener : public base::MessagePumpLibevent::Watcher { - public: - SigHupListener(const base::Closure& callback); - - 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: - base::Closure callback_; -}; - -SigHupListener::SigHupListener(const base::Closure& callback) - : callback_(callback) { -} - -void SigHupListener::OnFileCanReadWithoutBlocking(int fd) { - char buffer; - int result = HANDLE_EINTR(read(fd, &buffer, sizeof(buffer))); - if (result > 0) { - callback_.Run(); - } -} - -SigHupListener* g_config_updater = NULL; -int g_write_fd = 0; - -void HupSignalHandler(int signal) { - int r ALLOW_UNUSED = write(g_write_fd, "", 1); -} - -} // namespace - -namespace remoting { - -// RegisterHupSignalHandler registers a signal handler that writes a byte to a -// pipe each time SIGHUP 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 singal handler is very limited (but does include write). -bool RegisterHupSignalHandler(const base::Closure& callback) { - DCHECK(!g_config_updater); - MessageLoopForIO* message_loop = MessageLoopForIO::current(); - int pipefd[2]; - int result = pipe(pipefd); - if (result < 0) { - LOG(ERROR) << "Could not create SIGHUP pipe: " << errno; - return false; - } - g_write_fd = pipefd[1]; - g_config_updater = new SigHupListener(callback); - result = message_loop->WatchFileDescriptor( - pipefd[0], true, MessageLoopForIO::WATCH_READ, - &g_config_updater->controller, g_config_updater); - if (!result) { - delete g_config_updater; - g_config_updater = NULL; - LOG(ERROR) << "Failed to create SIGHUP detector task."; - return false; - } - if (signal(SIGHUP, HupSignalHandler) == SIG_ERR) { - delete g_config_updater; - g_config_updater = NULL; - LOG(ERROR) << "signal() failed: " << errno; - return false; - } - return true; -} - -} // namespace remoting diff --git a/remoting/host/posix/signal_handler.cc b/remoting/host/posix/signal_handler.cc new file mode 100644 index 0000000..69a3cc0 --- /dev/null +++ b/remoting/host/posix/signal_handler.cc @@ -0,0 +1,114 @@ +// 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 signal_number, const SignalHandler& handler) { + CHECK(signal_number < 256); // Don't want to worry about multi-byte writes. + if (!g_signal_listener) { + g_signal_listener = new SignalListener(); + } + if (!g_write_fd) { + int pipe_fd[2]; + int result = pipe(pipe_fd); + if (result < 0) { + LOG(ERROR) << "Could not create signal pipe: " << errno; + return false; + } + MessageLoopForIO* message_loop = MessageLoopForIO::current(); + result = message_loop->WatchFileDescriptor( + pipe_fd[0], true, MessageLoopForIO::WATCH_READ, + &g_signal_listener->controller, g_signal_listener); + if (!result) { + LOG(ERROR) << "Failed to create signal detector task."; + close(pipe_fd[0]); + close(pipe_fd[1]); + return false; + } + g_write_fd = pipe_fd[1]; + } + if (signal(signal_number, GlobalSignalHandler) == SIG_ERR) { + LOG(ERROR) << "signal() failed: " << errno; + return false; + } + g_signal_listener->AddSignalHandler(signal_number, handler); + return true; +} + +} // namespace remoting diff --git a/remoting/host/posix/sighup_listener.h b/remoting/host/posix/signal_handler.h index 48140a3..caf89ef 100644 --- a/remoting/host/posix/sighup_listener.h +++ b/remoting/host/posix/signal_handler.h @@ -6,17 +6,20 @@ // and trigger the specified callback. It is used on Linux and Mac in order to // reload the me2me host configuration. -#ifndef REMOTING_HOST_POSIX_SIGHUP_LISTENER_H_ -#define REMOTING_HOST_POSIX_SIGHUP_LISTENER_H_ +#ifndef REMOTING_HOST_POSIX_SIGNAL_HANDLER_H_ +#define REMOTING_HOST_POSIX_SIGNAL_HANDLER_H_ #include "base/callback_forward.h" namespace remoting { -// Register for SIGHUP notifications on the current thread, which must have -// an associated MessageLoopForIO. -bool RegisterHupSignalHandler(const base::Closure& callback); +typedef base::Callback<void(int)> SignalHandler; + +// Register for signal notifications on the current thread, which must have +// an associated MessageLoopForIO. Multiple calls to RegisterSignalHandler +// must all be made on the same thread. +bool RegisterSignalHandler(int signal_number, const SignalHandler& handler); } // namespace remoting -#endif // REMOTING_HOST_POSIX_SIGHUP_LISTENER_H_ +#endif // REMOTING_HOST_POSIX_SIGNAL_HANDLER_H_ |