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   brillo_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   brillo_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 (brillo_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