xref: /openbmc/phosphor-fan-presence/control/main.cpp (revision cd6f379813a27ee1ac41bb6d00f7f5ea18b6f48b)
1 /**
2  * Copyright © 2017 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "config.h"
17 
18 #ifndef CONTROL_USE_JSON
19 #include "../utils/flight_recorder.hpp"
20 #include "argument.hpp"
21 #include "manager.hpp"
22 #else
23 #include "json/manager.hpp"
24 #endif
25 #include "sdbusplus.hpp"
26 #include "sdeventplus.hpp"
27 
28 #include <phosphor-logging/log.hpp>
29 #include <sdbusplus/bus.hpp>
30 #include <sdeventplus/event.hpp>
31 #include <sdeventplus/source/signal.hpp>
32 #include <stdplus/signal.hpp>
33 
34 using namespace phosphor::fan::control;
35 using namespace phosphor::logging;
36 
37 int main(int argc, char* argv[])
38 {
39     auto event = phosphor::fan::util::SDEventPlus::getEvent();
40 
41 #ifndef CONTROL_USE_JSON
42     phosphor::fan::util::ArgumentParser args(argc, argv);
43     if (argc != 2)
44     {
45         args.usage(argv);
46         return 1;
47     }
48 
49     Mode mode;
50 
51     if (args["init"] == "true")
52     {
53         mode = Mode::init;
54     }
55     else if (args["control"] == "true")
56     {
57         mode = Mode::control;
58     }
59     else
60     {
61         args.usage(argv);
62         return 1;
63     }
64 #endif
65 
66     // Attach the event object to the bus object so we can
67     // handle both sd_events (for the timers) and dbus signals.
68     phosphor::fan::util::SDBusPlus::getBus().attach_event(
69         event.get(), SD_EVENT_PRIORITY_NORMAL);
70 
71     try
72     {
73 #ifdef CONTROL_USE_JSON
74         phosphor::fan::control::json::FlightRecorder::instance().log("main",
75                                                                      "Startup");
76         json::Manager manager(event);
77 
78         // Handle loading fan control's config file(s)
79         phosphor::fan::JsonConfig config(
80             std::bind(&json::Manager::load, &manager));
81 
82         // Enable SIGHUP handling to reload JSON configs
83         stdplus::signal::block(SIGHUP);
84         sdeventplus::source::Signal signal(
85             event, SIGHUP,
86             std::bind(&json::Manager::sighupHandler, &manager,
87                       std::placeholders::_1, std::placeholders::_2));
88 
89         // Enable SIGUSR1 handling to dump the flight recorder
90         stdplus::signal::block(SIGUSR1);
91         sdeventplus::source::Signal sigUsr1(
92             event, SIGUSR1,
93             std::bind(&json::Manager::sigUsr1Handler, &manager,
94                       std::placeholders::_1, std::placeholders::_2));
95 
96         phosphor::fan::util::SDBusPlus::getBus().request_name(CONTROL_BUSNAME);
97 #else
98         Manager manager(phosphor::fan::util::SDBusPlus::getBus(), event, mode);
99 
100         // Init mode will just set fans to max and delay
101         if (mode == Mode::init)
102         {
103             manager.doInit(event);
104             return 0;
105         }
106 #endif
107         return event.loop();
108     }
109     // Log the useful metadata on these exceptions and let the app
110     // return 1 so it is restarted without a core dump.
111     catch (const phosphor::fan::util::DBusServiceError& e)
112     {
113         log<level::ERR>("Uncaught DBus service lookup failure exception",
114                         entry("PATH=%s", e.path.c_str()),
115                         entry("INTERFACE=%s", e.interface.c_str()));
116     }
117     catch (const phosphor::fan::util::DBusMethodError& e)
118     {
119         log<level::ERR>("Uncaught DBus method failure exception",
120                         entry("BUSNAME=%s", e.busName.c_str()),
121                         entry("PATH=%s", e.path.c_str()),
122                         entry("INTERFACE=%s", e.interface.c_str()),
123                         entry("METHOD=%s", e.method.c_str()));
124     }
125     catch (const phosphor::fan::util::DBusPropertyError& e)
126     {
127         log<level::ERR>("Uncaught DBus property access failure exception",
128                         entry("BUSNAME=%s", e.busName.c_str()),
129                         entry("PATH=%s", e.path.c_str()),
130                         entry("INTERFACE=%s", e.interface.c_str()),
131                         entry("PROPERTY=%s", e.property.c_str()));
132     }
133     catch (std::exception& e)
134     {
135 #ifdef CONTROL_USE_JSON
136         phosphor::fan::control::json::FlightRecorder::instance().log(
137             "main", "Unexpected exception exit");
138         phosphor::fan::control::json::FlightRecorder::instance().dump();
139 #endif
140         throw;
141     }
142 
143 #ifdef CONTROL_USE_JSON
144     phosphor::fan::control::json::FlightRecorder::instance().log(
145         "main", "Abnormal exit");
146     phosphor::fan::control::json::FlightRecorder::instance().dump();
147 #endif
148 
149     return 1;
150 }
151