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
15namespace brillo {
16
17Daemon::Daemon() : exit_code_{EX_OK} {
18  brillo_message_loop_.SetAsCurrent();
19}
20
21Daemon::~Daemon() {
22}
23
24int 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
43void Daemon::Quit() { QuitWithExitCode(EX_OK); }
44
45void Daemon::QuitWithExitCode(int exit_code) {
46  exit_code_ = exit_code;
47  message_loop_.PostTask(FROM_HERE, QuitClosure());
48}
49
50void Daemon::RegisterHandler(
51    int signal,
52    const AsynchronousSignalHandlerInterface::SignalHandler& callback) {
53  async_signal_handler_.RegisterHandler(signal, callback);
54}
55
56void Daemon::UnregisterHandler(int signal) {
57  async_signal_handler_.UnregisterHandler(signal);
58}
59
60int 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
71void Daemon::OnShutdown(int* /* exit_code */) {
72  // Do nothing.
73}
74
75bool Daemon::OnRestart() {
76  // Not handled.
77  return false;  // Returning false will shut down the daemon instead.
78}
79
80bool Daemon::Shutdown(const signalfd_siginfo& /* info */) {
81  Quit();
82  return true;  // Unregister the signal handler.
83}
84
85bool 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