1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // TODO(jamiewalch): Add unit tests for this.
7 #include "remoting/host/posix/signal_handler.h"
15 #include "base/compiler_specific.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/message_loop/message_pump_libevent.h"
18 #include "base/posix/eintr_wrapper.h"
19 #include "base/threading/platform_thread.h"
24 class SignalListener
: public base::MessagePumpLibevent::Watcher
{
28 void AddSignalHandler(int signal
, const SignalHandler
& handler
);
30 void OnFileCanReadWithoutBlocking(int fd
) override
;
31 void OnFileCanWriteWithoutBlocking(int fd
) override
{}
33 // WatchFileDescriptor needs a controller through which the operation can be
34 // canceled. We don't use it, but this is as good a place as any to store it.
35 base::MessagePumpLibevent::FileDescriptorWatcher controller
;
38 typedef std::pair
<int, SignalHandler
> SignalAndHandler
;
39 typedef std::list
<SignalAndHandler
> SignalHandlers
;
40 SignalHandlers signal_handlers_
;
43 SignalListener::SignalListener() {
46 void SignalListener::AddSignalHandler(int signal
,
47 const SignalHandler
& handler
) {
48 signal_handlers_
.push_back(SignalAndHandler(signal
, handler
));
51 void SignalListener::OnFileCanReadWithoutBlocking(int fd
) {
53 int result
= HANDLE_EINTR(read(fd
, &buffer
, sizeof(buffer
)));
55 for (SignalHandlers::const_iterator i
= signal_handlers_
.begin();
56 i
!= signal_handlers_
.end();
58 if (i
->first
== buffer
) {
59 i
->second
.Run(i
->first
);
65 SignalListener
* g_signal_listener
= nullptr;
68 void GlobalSignalHandler(int signal
) {
70 ignore_result(write(g_write_fd
, &byte
, 1));
75 // RegisterSignalHandler registers a signal handler that writes a byte to a
76 // pipe each time a signal is received. The read end of the pipe is registered
77 // with the current MessageLoop (which must be of type IO); whenever the pipe
78 // is readable, it invokes the specified callback.
80 // This arrangement is required because the set of system APIs that are safe to
81 // call from a signal handler is very limited (but does include write).
82 bool RegisterSignalHandler(int signal_number
, const SignalHandler
& handler
) {
83 CHECK(signal_number
< 256); // Don't want to worry about multi-byte writes.
84 if (!g_signal_listener
) {
85 g_signal_listener
= new SignalListener();
89 int result
= pipe(pipe_fd
);
91 LOG(ERROR
) << "Could not create signal pipe: " << errno
;
94 base::MessageLoopForIO
* message_loop
= base::MessageLoopForIO::current();
96 message_loop
->WatchFileDescriptor(pipe_fd
[0],
98 base::MessageLoopForIO::WATCH_READ
,
99 &g_signal_listener
->controller
,
102 LOG(ERROR
) << "Failed to create signal detector task.";
107 g_write_fd
= pipe_fd
[1];
109 if (signal(signal_number
, GlobalSignalHandler
) == SIG_ERR
) {
110 LOG(ERROR
) << "signal() failed: " << errno
;
113 g_signal_listener
->AddSignalHandler(signal_number
, handler
);
117 } // namespace remoting