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 #include <fstream> 35 36 using namespace phosphor::fan::control; 37 using namespace phosphor::logging; 38 39 #ifdef CONTROL_USE_JSON 40 void dumpFlightRecorder() 41 { 42 nlohmann::json data; 43 phosphor::fan::control::json::FlightRecorder::instance().dump(data); 44 std::ofstream file{json::Manager::dumpFile}; 45 file << std::setw(4) << data; 46 } 47 #endif 48 49 int main(int argc, char* argv[]) 50 { 51 auto event = phosphor::fan::util::SDEventPlus::getEvent(); 52 53 #ifndef CONTROL_USE_JSON 54 phosphor::fan::util::ArgumentParser args(argc, argv); 55 if (argc != 2) 56 { 57 args.usage(argv); 58 return 1; 59 } 60 61 Mode mode; 62 63 if (args["init"] == "true") 64 { 65 mode = Mode::init; 66 } 67 else if (args["control"] == "true") 68 { 69 mode = Mode::control; 70 } 71 else 72 { 73 args.usage(argv); 74 return 1; 75 } 76 #endif 77 78 // Attach the event object to the bus object so we can 79 // handle both sd_events (for the timers) and dbus signals. 80 phosphor::fan::util::SDBusPlus::getBus().attach_event( 81 event.get(), SD_EVENT_PRIORITY_NORMAL); 82 83 try 84 { 85 #ifdef CONTROL_USE_JSON 86 phosphor::fan::control::json::FlightRecorder::instance().log("main", 87 "Startup"); 88 json::Manager manager(event); 89 90 // Handle loading fan control's config file(s) 91 phosphor::fan::JsonConfig config( 92 std::bind(&json::Manager::load, &manager)); 93 94 // Enable SIGHUP handling to reload JSON configs 95 stdplus::signal::block(SIGHUP); 96 sdeventplus::source::Signal signal( 97 event, SIGHUP, 98 std::bind(&json::Manager::sighupHandler, &manager, 99 std::placeholders::_1, std::placeholders::_2)); 100 101 // Enable SIGUSR1 handling to dump the flight recorder 102 stdplus::signal::block(SIGUSR1); 103 sdeventplus::source::Signal sigUsr1( 104 event, SIGUSR1, 105 std::bind(&json::Manager::sigUsr1Handler, &manager, 106 std::placeholders::_1, std::placeholders::_2)); 107 108 phosphor::fan::util::SDBusPlus::getBus().request_name(CONTROL_BUSNAME); 109 #else 110 Manager manager(phosphor::fan::util::SDBusPlus::getBus(), event, mode); 111 112 // Init mode will just set fans to max and delay 113 if (mode == Mode::init) 114 { 115 manager.doInit(event); 116 return 0; 117 } 118 #endif 119 return event.loop(); 120 } 121 // Log the useful metadata on these exceptions and let the app 122 // return 1 so it is restarted without a core dump. 123 catch (const phosphor::fan::util::DBusServiceError& e) 124 { 125 log<level::ERR>("Uncaught DBus service lookup failure exception", 126 entry("PATH=%s", e.path.c_str()), 127 entry("INTERFACE=%s", e.interface.c_str())); 128 } 129 catch (const phosphor::fan::util::DBusMethodError& e) 130 { 131 log<level::ERR>("Uncaught DBus method failure exception", 132 entry("BUSNAME=%s", e.busName.c_str()), 133 entry("PATH=%s", e.path.c_str()), 134 entry("INTERFACE=%s", e.interface.c_str()), 135 entry("METHOD=%s", e.method.c_str())); 136 } 137 catch (const phosphor::fan::util::DBusPropertyError& e) 138 { 139 log<level::ERR>("Uncaught DBus property access failure exception", 140 entry("BUSNAME=%s", e.busName.c_str()), 141 entry("PATH=%s", e.path.c_str()), 142 entry("INTERFACE=%s", e.interface.c_str()), 143 entry("PROPERTY=%s", e.property.c_str())); 144 } 145 catch (std::exception& e) 146 { 147 #ifdef CONTROL_USE_JSON 148 phosphor::fan::control::json::FlightRecorder::instance().log( 149 "main", "Unexpected exception exit"); 150 dumpFlightRecorder(); 151 #endif 152 throw; 153 } 154 155 #ifdef CONTROL_USE_JSON 156 phosphor::fan::control::json::FlightRecorder::instance().log( 157 "main", "Abnormal exit"); 158 dumpFlightRecorder(); 159 #endif 160 161 return 1; 162 } 163