diff --git a/debian/changelog b/debian/changelog index e9cc8c0..46f9b7c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -fancon (0.23.5) focal; urgency=low +fancon (0.23.6) focal; urgency=low * Initial release. Closes: #00000 diff --git a/debian/fancon-nvidia.service b/debian/fancon-nvidia.service index df59b6b..b98ad71 100644 --- a/debian/fancon-nvidia.service +++ b/debian/fancon-nvidia.service @@ -8,7 +8,7 @@ Requires=graphical.target [Service] Type=oneshot User=root -ExecStart=/usr/bin/fancon nv-init +ExecStart=/usr/bin/fancon nv-init -v [Install] WantedBy=graphical.target \ No newline at end of file diff --git a/debian/fancon-resume.service b/debian/fancon-resume.service index 7ffdec0..acf74bd 100644 --- a/debian/fancon-resume.service +++ b/debian/fancon-resume.service @@ -6,7 +6,7 @@ After=suspend.target hibernate.target hybrid-sleep.target suspend-then-hibernate [Service] Type=oneshot User=root -ExecStart=/usr/bin/fancon recover +ExecStart=/usr/bin/fancon recover -v [Install] WantedBy=suspend.target hibernate.target hybrid-sleep.target suspend-then-hibernate.target diff --git a/debian/fancon.service b/debian/fancon.service index dcc0e2f..f151395 100644 --- a/debian/fancon.service +++ b/debian/fancon.service @@ -6,7 +6,7 @@ After=multi-user.target [Service] Type=simple User=root -ExecStart=/usr/bin/fancon service +ExecStart=/usr/bin/fancon service -v ExecStop=/usr/bin/fancon stop-service ExecReload=/usr/bin/fancon reload Restart=on-failure diff --git a/src/Controller.cpp b/src/Controller.cpp index e9e0aab..660c4e7 100644 --- a/src/Controller.cpp +++ b/src/Controller.cpp @@ -15,7 +15,8 @@ fc::Controller::Controller(path conf_path_) : config_path(move(conf_path_)) { fc::Controller::~Controller() { disable_all(); } -FanStatus fc::Controller::status(const string &flabel) const { +FanStatus fc::Controller::status(const string &flabel) { + const lock_guard lg(tasks_mutex[flabel]); const auto it = tasks.find(flabel); if (it == tasks.end()) return FanStatus::FanStatus_Status_DISABLED; @@ -25,12 +26,15 @@ FanStatus fc::Controller::status(const string &flabel) const { } void fc::Controller::enable(fc::FanInterface &f, bool enable_all_dell) { + tasks_mutex[f.label].lock(); if (tasks.count(f.label) > 0) return; // Dell fans can only be enabled/disabled togther - if (f.type() == DevType::DELL && enable_all_dell) + if (f.type() == DevType::DELL && enable_all_dell) { + tasks_mutex[f.label].unlock(); return enable_dell_fans(); + } if (!f.pre_start_check()) return; @@ -44,6 +48,7 @@ void fc::Controller::enable(fc::FanInterface &f, bool enable_all_dell) { }); LOG(llvl::trace) << f.label << ": enabled"; + tasks_mutex[f.label].unlock(); } void fc::Controller::enable_all() { @@ -54,13 +59,16 @@ void fc::Controller::enable_all() { } void fc::Controller::disable(const string &flabel, bool disable_all_dell) { + tasks_mutex[flabel].lock(); const auto it = tasks.find(flabel); if (it == tasks.end()) return; // Dell fans can only be enabled/disabled togther - if (devices.fans.at(flabel)->type() == DevType::DELL && disable_all_dell) + if (devices.fans.at(flabel)->type() == DevType::DELL && disable_all_dell) { + tasks_mutex[flabel].unlock(); return disable_dell_fans(); + } tasks.erase(flabel); if (const auto fit = devices.fans.find(flabel); fit != devices.fans.end()) @@ -68,18 +76,17 @@ void fc::Controller::disable(const string &flabel, bool disable_all_dell) { LOG(llvl::trace) << flabel << ": disabled"; notify_status_observers(flabel); + tasks_mutex[flabel].unlock(); } void fc::Controller::disable_all() { - vector disabled_fans; + vector fans; for (const auto &[flabel, task] : tasks) - disabled_fans.push_back(flabel); - - tasks.clear(); - for (const auto &flabel : disabled_fans) - notify_status_observers(flabel); + fans.push_back(flabel); LOG(llvl::trace) << "Disabling all"; + for (const auto &flabel : fans) + disable(flabel, false); } void fc::Controller::reload(bool just_started) { @@ -144,15 +151,17 @@ void fc::Controller::test(fc::FanInterface &fan, bool forced, bool blocking, LOG(llvl::info) << fan << ": test complete"; const thread t([&] { tasks.erase(fan.label); }); - // Only write to file when no other fan are still testing - if (tests_running() == 0) - to_file(false); + { + // Only write to file when no other fan are still testing + lock_guard lg(test_mutex); + if (tests_running() == 0) + to_file(false); + } enable(fan); }; - const auto [it, success] = - tasks.try_emplace(fan.label, move(test_func), test_status); + const auto[it, success] = tasks.try_emplace(fan.label, move(test_func), test_status); if (!success) test(fan, forced, blocking, test_status); @@ -257,45 +266,40 @@ void fc::Controller::merge(Devices &d, bool replace_on_match, bool deep_cmp) { } }; - m(d.fans, devices.fans, - [&](auto &old_it, const string &old_key, const string &new_key, auto &dev) { - // On match; re-insert device as the key may have changed - const auto re_insert = [&] { - devices.fans.erase(old_it); - return devices.fans.emplace(new_key, move(dev)); - }; - const FanStatus fstatus = status(old_key); - if (fstatus == FanStatus::FanStatus_Status_DISABLED) { - re_insert(); - } else if (fstatus == FanStatus::FanStatus_Status_ENABLED) { - disable(old_it->first, false); - auto [it, success] = re_insert(); - enable(*it->second, true); - } else if (fstatus == FanStatus::FanStatus_Status_TESTING) { - const auto test_status = tasks.find(old_key)->second.test_status; - disable(old_key, false); - auto [it, success] = re_insert(); - test(*it->second, true, false, test_status); - } - }); - - m(d.sensors, devices.sensors, - [&](auto &old_it, [[maybe_unused]] const string &old_key, - const string &new_key, auto &dev) { - // On match; re-insert device as the key may have changed - devices.sensors.erase(old_it); - devices.sensors.emplace(new_key, move(dev)); - }); + m(d.fans, devices.fans, [&](auto &old_it, const string &old_key, const string &new_key, auto &dev) { + // On match; re-insert device as the key may have changed + const auto re_insert = [&] { + devices.fans.erase(old_it); + return devices.fans.emplace(new_key, move(dev)); + }; + const FanStatus fstatus = status(old_key); + if (fstatus == FanStatus::FanStatus_Status_DISABLED) { + re_insert(); + } else if (fstatus == FanStatus::FanStatus_Status_ENABLED) { + disable(old_it->first, false); + auto[it, success] = re_insert(); + enable(*it->second, true); + } else if (fstatus == FanStatus::FanStatus_Status_TESTING) { + const auto test_status = tasks.find(old_key)->second.test_status; + disable(old_key, false); + auto[it, success] = re_insert(); + test(*it->second, true, false, test_status); + } + }); + + m(d.sensors, devices.sensors, [&](auto &old_it, [[maybe_unused]] const string &old_key, + const string &new_key, auto &dev) { + // On match; re-insert device as the key may have changed + devices.sensors.erase(old_it); + devices.sensors.emplace(new_key, move(dev)); + }); } -void fc::Controller::remove_devices_not_in( - std::initializer_list> l) { +void fc::Controller::remove_devices_not_in(std::initializer_list> l) { // Remove items not in conf_devs or enumerated but in devices for (const auto &p : devices.fans) { const auto &flabel = std::get<0>(p); - if (!std::any_of(l.begin(), l.end(), [&](const Devices &l) { - return l.fans.contains(flabel); - })) { + if (!std::any_of(l.begin(), l.end(), [&](const Devices &l) { return l.fans.contains(flabel); })) { disable(flabel); devices.fans.erase(flabel); } @@ -303,9 +307,7 @@ void fc::Controller::remove_devices_not_in( for (const auto &p : devices.sensors) { const auto &slabel = std::get<0>(p); - if (!std::any_of(l.begin(), l.end(), [&](const Devices &l) { - return l.sensors.contains(slabel); - })) { + if (!std::any_of(l.begin(), l.end(), [&](const Devices &l) { return l.sensors.contains(slabel); })) { devices.sensors.erase(slabel); } } @@ -319,22 +321,24 @@ void fc::Controller::to_file(bool backup) { LOG(llvl::info) << "Moved previous config to: " << backup_path; } - std::ofstream ofs(config_path); fc_pb::Controller c; to(c); string out_s; google::protobuf::TextFormat::Printer printer; printer.SetUseShortRepeatedPrimitives(true); - printer.PrintToString(c, &out_s); - ofs << out_s; - if (ofs) { + std::ofstream ofs(config_path); + ofs.exceptions(); + try { + ofs.open(config_path); + ofs << out_s; update_config_write_time(); notify_devices_observers(); - } else { - LOG(llvl::error) << "Failed to write config to: " << config_path; + LOG(llvl::info) << "Config written to: " << config_path; + } catch (std::ios_base::failure &e) { + LOG(llvl::error) << "Failed to write config: " << e.code() << " - " << e.what(); } } diff --git a/src/Controller.hpp b/src/Controller.hpp index b6d42db..e21a871 100644 --- a/src/Controller.hpp +++ b/src/Controller.hpp @@ -40,11 +40,13 @@ class Controller { Devices devices; map tasks; + map tasks_mutex; + mutex test_mutex; list device_observers; list status_observers; Util::RemovableMutex device_observers_mutex, status_observers_mutex; - FanStatus status(const string &flabel) const; + FanStatus status(const string &flabel); void enable(fc::FanInterface &fan, bool enable_all_dell = true); void enable_all(); void disable(const string &flabel, bool disable_all_dell = true); diff --git a/src/FanTask.cpp b/src/FanTask.cpp index ab39ed1..74b3676 100644 --- a/src/FanTask.cpp +++ b/src/FanTask.cpp @@ -1,7 +1,13 @@ #include "FanTask.hpp" fc::FanTask::FanTask(function f) - : t(thread([this](auto f) { f(run); }, move(f))) {} + : t(thread([this](auto f) { + try { + f(run); + } catch (const std::exception &e) { + LOG(llvl::fatal) << e.what(); + } +}, move(f))) {} fc::FanTask::FanTask(function f, shared_ptr> testing_status)