/** * Copyright © 2022 IBM Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #ifndef CONTROL_USE_JSON #include "manager.hpp" #include #else #include "../utils/flight_recorder.hpp" #include "json/manager.hpp" #endif #include "dbus_paths.hpp" #include "sdbusplus.hpp" #include "sdeventplus.hpp" #include #include #include #include #include #include using namespace phosphor::fan::control; using namespace phosphor::logging; #ifdef CONTROL_USE_JSON void dumpFlightRecorder() { nlohmann::json data; phosphor::fan::control::json::FlightRecorder::instance().dump(data); std::ofstream file{json::Manager::dumpFile}; file << std::setw(4) << data; } #endif int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) { auto event = phosphor::fan::util::SDEventPlus::getEvent(); #ifndef CONTROL_USE_JSON CLI::App app{"Phosphor Fan Control"}; bool init = false; bool control = false; app.add_flag("-i,--init", init, "Sets fans to full speed, delays, exits"); app.add_flag("-c,--control", control, "Start fan control algorithm"); app.require_option(); try { app.parse(argc, argv); } catch (const CLI::Error& e) { return app.exit(e); } Mode mode; if (init) { mode = Mode::init; } else if (control) { mode = Mode::control; } #endif // Attach the event object to the bus object so we can // handle both sd_events (for the timers) and dbus signals. phosphor::fan::util::SDBusPlus::getBus().attach_event( event.get(), SD_EVENT_PRIORITY_NORMAL); try { #ifdef CONTROL_USE_JSON phosphor::fan::control::json::FlightRecorder::instance().log( "main", "Startup"); json::Manager manager(event); // Handle loading fan control's config file(s) phosphor::fan::JsonConfig config( std::bind(&json::Manager::load, &manager)); // Enable SIGHUP handling to reload JSON configs stdplus::signal::block(SIGHUP); sdeventplus::source::Signal signal( event, SIGHUP, std::bind(&json::Manager::sighupHandler, &manager, std::placeholders::_1, std::placeholders::_2)); // Enable SIGUSR1 handling to dump the flight recorder stdplus::signal::block(SIGUSR1); sdeventplus::source::Signal sigUsr1( event, SIGUSR1, std::bind(&json::Manager::dumpDebugData, &manager, std::placeholders::_1, std::placeholders::_2)); phosphor::fan::util::SDBusPlus::getBus().request_name(CONTROL_BUSNAME); #else Manager manager(phosphor::fan::util::SDBusPlus::getBus(), event, mode); // Init mode will just set fans to max and delay if (mode == Mode::init) { manager.doInit(event); return 0; } #endif return event.loop(); } // Log the useful metadata on these exceptions and let the app // return 1 so it is restarted without a core dump. catch (const phosphor::fan::util::DBusServiceError& e) { log("Uncaught DBus service lookup failure exception", entry("PATH=%s", e.path.c_str()), entry("INTERFACE=%s", e.interface.c_str())); } catch (const phosphor::fan::util::DBusMethodError& e) { log("Uncaught DBus method failure exception", entry("BUSNAME=%s", e.busName.c_str()), entry("PATH=%s", e.path.c_str()), entry("INTERFACE=%s", e.interface.c_str()), entry("METHOD=%s", e.method.c_str())); } catch (const phosphor::fan::util::DBusPropertyError& e) { log("Uncaught DBus property access failure exception", entry("BUSNAME=%s", e.busName.c_str()), entry("PATH=%s", e.path.c_str()), entry("INTERFACE=%s", e.interface.c_str()), entry("PROPERTY=%s", e.property.c_str())); } catch (std::exception& e) { #ifdef CONTROL_USE_JSON phosphor::fan::control::json::FlightRecorder::instance().log( "main", "Unexpected exception exit"); dumpFlightRecorder(); #endif throw; } #ifdef CONTROL_USE_JSON phosphor::fan::control::json::FlightRecorder::instance().log( "main", "Abnormal exit"); dumpFlightRecorder(); #endif return 1; }