1 // Copyright 2014 The Chromium OS 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.
4
5 #include <brillo/daemons/daemon.h>
6
7 #include <sysexits.h>
8
9 #include <base/bind.h>
10 #include <base/files/file_path.h>
11 #include <base/files/file_util.h>
12 #include <base/logging.h>
13 #include <base/run_loop.h>
14
15 namespace brillo {
16
Daemon()17 Daemon::Daemon() : exit_code_{EX_OK} {
18 message_loop_.SetAsCurrent();
19 }
20
~Daemon()21 Daemon::~Daemon() {
22 }
23
Run()24 int Daemon::Run() {
25 int exit_code = OnInit();
26 if (exit_code != EX_OK)
27 return exit_code;
28
29 message_loop_.Run();
30
31 OnShutdown(&exit_code_);
32
33 // base::RunLoop::QuitClosure() causes the message loop to quit
34 // immediately, even if pending tasks are still queued.
35 // Run a secondary loop to make sure all those are processed.
36 // This becomes important when working with D-Bus since dbus::Bus does
37 // a bunch of clean-up tasks asynchronously when shutting down.
38 while (message_loop_.RunOnce(false /* may_block */)) {}
39
40 return exit_code_;
41 }
42
Quit()43 void Daemon::Quit() { QuitWithExitCode(EX_OK); }
44
QuitWithExitCode(int exit_code)45 void Daemon::QuitWithExitCode(int exit_code) {
46 exit_code_ = exit_code;
47 message_loop_.PostTask(FROM_HERE, QuitClosure());
48 }
49
RegisterHandler(int signal,const AsynchronousSignalHandlerInterface::SignalHandler & callback)50 void Daemon::RegisterHandler(
51 int signal,
52 const AsynchronousSignalHandlerInterface::SignalHandler& callback) {
53 async_signal_handler_.RegisterHandler(signal, callback);
54 }
55
UnregisterHandler(int signal)56 void Daemon::UnregisterHandler(int signal) {
57 async_signal_handler_.UnregisterHandler(signal);
58 }
59
OnInit()60 int Daemon::OnInit() {
61 async_signal_handler_.Init();
62 for (int signal : {SIGTERM, SIGINT}) {
63 async_signal_handler_.RegisterHandler(
64 signal, base::Bind(&Daemon::Shutdown, base::Unretained(this)));
65 }
66 async_signal_handler_.RegisterHandler(
67 SIGHUP, base::Bind(&Daemon::Restart, base::Unretained(this)));
68 return EX_OK;
69 }
70
OnShutdown(int *)71 void Daemon::OnShutdown(int* /* exit_code */) {
72 // Do nothing.
73 }
74
OnRestart()75 bool Daemon::OnRestart() {
76 // Not handled.
77 return false; // Returning false will shut down the daemon instead.
78 }
79
Shutdown(const signalfd_siginfo &)80 bool Daemon::Shutdown(const signalfd_siginfo& /* info */) {
81 Quit();
82 return true; // Unregister the signal handler.
83 }
84
Restart(const signalfd_siginfo &)85 bool Daemon::Restart(const signalfd_siginfo& /* info */) {
86 if (OnRestart())
87 return false; // Keep listening to the signal.
88 Quit();
89 return true; // Unregister the signal handler.
90 }
91
92 } // namespace brillo
93