From 6d735a5733e79f4b35c3c825f53fd42ae29a3836 Mon Sep 17 00:00:00 2001 From: sawinglogz <3787776-sawinglogz@users.noreply.gitlab.com> Date: Thu, 15 Aug 2019 15:49:40 -0400 Subject: [PATCH] Add Day::removeMachine to detect and clean up dangling references rather than crashing when rebuilding data. This doesn't yet address the root cause, but it will prevent crashing if other similar bugs exist. --- oscar/SleepLib/day.cpp | 30 ++++++++++++++++++++++++++++++ oscar/SleepLib/day.h | 6 +++++- oscar/SleepLib/machine.cpp | 5 +++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/oscar/SleepLib/day.cpp b/oscar/SleepLib/day.cpp index 7f290d85..b2dda6be 100644 --- a/oscar/SleepLib/day.cpp +++ b/oscar/SleepLib/day.cpp @@ -1,5 +1,6 @@ /* SleepLib Day Class Implementation * + * Copyright (c) 2019 The OSCAR Team * Copyright (c) 2011-2018 Mark Watkins * * This file is subject to the terms and conditions of the GNU General Public @@ -1341,6 +1342,35 @@ bool Day::hasMachine(Machine * mach) return false; } +void Day::removeMachine(Machine * mach) +{ + // Yell about and fix any dangling references rather than possibly crashing later. + // + // This has no functional use and can be removed when the data structures are cleaned up + // with better encapsulation and fewer unnecessary references between each other. + + QList list = sessions; // make a copy so the iterator doesn't get broken by removals + for (auto & sess : list) { + if (sess->machine() == mach) { + // This indicates a problem with the Machine class not tracking all of its sessions, for + // example if there's a duplicate session ID. + qCritical() << "Day object" << this->date().toString() + << "session" << sess->session() << "refers to machine" << mach->serial(); + removeSession(sess); + } + } + + for (auto & m : machines.keys()) { + if (machines[m] == mach) { + // This indicates a problem internal to the Day class, since removeSession should remove + // machines from this list if there are no longer any sessions pointing to it. + qCritical() << "Day object" << this->date().toString() + << "refers to machine" << mach->serial(); + machines.remove(m); + } + } +} + QString Day::getCPAPMode() { Machine * mach = machine(MT_CPAP); diff --git a/oscar/SleepLib/day.h b/oscar/SleepLib/day.h index bb74e48c..0415d8c3 100644 --- a/oscar/SleepLib/day.h +++ b/oscar/SleepLib/day.h @@ -1,5 +1,6 @@ -/* SleepLib Day Class Header +/* SleepLib Day Class Header * + * Copyright (c) 2019 The OSCAR Team * Copyright (C) 2011-2018 Mark Watkins * * This file is subject to the terms and conditions of the GNU General Public @@ -100,6 +101,9 @@ class Day //! \brief Returns true if any sessions have records matching specific machine type bool searchMachine(MachineType mt); + //! \brief Removes any lingering references to a specific machine record and emits a warning if there were any + void removeMachine(Machine * mach); + //! \brief Returns the Average of all Sessions setting 'code' for this day EventDataType settings_avg(ChannelID code); diff --git a/oscar/SleepLib/machine.cpp b/oscar/SleepLib/machine.cpp index 17a166cd..cf209ba1 100644 --- a/oscar/SleepLib/machine.cpp +++ b/oscar/SleepLib/machine.cpp @@ -519,6 +519,7 @@ bool Machine::Purge(int secret) // Create a copy of the list so the hash can be manipulated QList sessions = sessionlist.values(); + QList days = day.values(); // Clean up any loaded sessions from memory first.. //bool success = true; @@ -533,6 +534,10 @@ bool Machine::Purge(int secret) delete sess; } + // Make sure there aren't any dangling references to this machine + for (auto & d : days) { + d->removeMachine(this); + } // Remove EVERYTHING under Events folder.. QString eventspath = getEventsPath();