• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <time.h>
9 
10 #include <base/bind.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_.PostTask(
30       base::Bind(&Daemon::OnEventLoopStartedTask, base::Unretained(this)));
31   message_loop_.Run();
32 
33   OnShutdown(&exit_code_);
34 
35   // base::RunLoop::QuitClosure() causes the message loop to quit
36   // immediately, even if pending tasks are still queued.
37   // Run a secondary loop to make sure all those are processed.
38   // This becomes important when working with D-Bus since dbus::Bus does
39   // a bunch of clean-up tasks asynchronously when shutting down.
40   while (message_loop_.RunOnce(false /* may_block */)) {}
41 
42   return exit_code_;
43 }
44 
Quit()45 void Daemon::Quit() { QuitWithExitCode(EX_OK); }
46 
QuitWithExitCode(int exit_code)47 void Daemon::QuitWithExitCode(int exit_code) {
48   exit_code_ = exit_code;
49   message_loop_.PostTask(FROM_HERE, QuitClosure());
50 }
51 
RegisterHandler(int signal,const AsynchronousSignalHandlerInterface::SignalHandler & callback)52 void Daemon::RegisterHandler(
53     int signal,
54     const AsynchronousSignalHandlerInterface::SignalHandler& callback) {
55   async_signal_handler_.RegisterHandler(signal, callback);
56 }
57 
UnregisterHandler(int signal)58 void Daemon::UnregisterHandler(int signal) {
59   async_signal_handler_.UnregisterHandler(signal);
60 }
61 
OnInit()62 int Daemon::OnInit() {
63   async_signal_handler_.Init();
64   for (int signal : {SIGTERM, SIGINT}) {
65     async_signal_handler_.RegisterHandler(
66         signal, base::Bind(&Daemon::Shutdown, base::Unretained(this)));
67   }
68   async_signal_handler_.RegisterHandler(
69       SIGHUP, base::Bind(&Daemon::Restart, base::Unretained(this)));
70   return EX_OK;
71 }
72 
OnEventLoopStarted()73 int Daemon::OnEventLoopStarted() {
74   // Do nothing.
75   return EX_OK;
76 }
77 
OnShutdown(int *)78 void Daemon::OnShutdown(int* /* exit_code */) {
79   // Do nothing.
80 }
81 
OnRestart()82 bool Daemon::OnRestart() {
83   // Not handled.
84   return false;  // Returning false will shut down the daemon instead.
85 }
86 
Shutdown(const signalfd_siginfo &)87 bool Daemon::Shutdown(const signalfd_siginfo& /* info */) {
88   Quit();
89   return true;  // Unregister the signal handler.
90 }
91 
Restart(const signalfd_siginfo &)92 bool Daemon::Restart(const signalfd_siginfo& /* info */) {
93   if (OnRestart())
94     return false;  // Keep listening to the signal.
95   Quit();
96   return true;  // Unregister the signal handler.
97 }
98 
OnEventLoopStartedTask()99 void Daemon::OnEventLoopStartedTask() {
100   int exit_code = OnEventLoopStarted();
101   if (exit_code != EX_OK)
102     QuitWithExitCode(exit_code);
103 }
104 
UpdateLogSymlinks(const base::FilePath & latest_log_symlink,const base::FilePath & previous_log_symlink,const base::FilePath & log_file)105 void UpdateLogSymlinks(const base::FilePath& latest_log_symlink,
106                        const base::FilePath& previous_log_symlink,
107                        const base::FilePath& log_file) {
108   base::DeleteFile(previous_log_symlink, false);
109   base::Move(latest_log_symlink, previous_log_symlink);
110   if (!base::CreateSymbolicLink(log_file.BaseName(), latest_log_symlink)) {
111     PLOG(ERROR) << "Unable to create symbolic link from "
112                 << latest_log_symlink.value() << " to " << log_file.value();
113   }
114 }
115 
GetTimeAsLogString(const base::Time & time)116 std::string GetTimeAsLogString(const base::Time& time) {
117   time_t utime = time.ToTimeT();
118   struct tm tm;
119   CHECK_EQ(localtime_r(&utime, &tm), &tm);
120   char str[16];
121   CHECK_EQ(strftime(str, sizeof(str), "%Y%m%d-%H%M%S", &tm), 15UL);
122   return std::string(str);
123 }
124 
125 }  // namespace brillo
126