summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Dirk Hohndel <dirk@hohndel.org>2014-08-23 07:13:37 -0700
committerGravatar Dirk Hohndel <dirk@hohndel.org>2014-08-23 07:23:42 -0700
commitfb371c063352715c84d2b3b85d16d6c0937b039b (patch)
tree47d7a689c532b0a3e278f015d3f48e514428fc78
parent3e4c30735c835e8cc27ddbbffe3c4c61141f7d2e (diff)
downloadsubsurface-fb371c063352715c84d2b3b85d16d6c0937b039b.tar.gz
TankBar: don't risk dereferencing stale pointers
Basically we could end up in a situation where the plotInfo is no longer valid, yet the model changes and triggers a redraw before the new data is passed into the TankBar. Instead of chasing that race condition it seemed much easier to just copy the plot_data entries and the gas information in the dive. Fixes #716 Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r--qt-ui/profile/tankitem.cpp27
-rw-r--r--qt-ui/profile/tankitem.h5
2 files changed, 20 insertions, 12 deletions
diff --git a/qt-ui/profile/tankitem.cpp b/qt-ui/profile/tankitem.cpp
index a5ec5050c..42692aacd 100644
--- a/qt-ui/profile/tankitem.cpp
+++ b/qt-ui/profile/tankitem.cpp
@@ -9,8 +9,8 @@
TankItem::TankItem(QObject *parent) :
QGraphicsRectItem(),
dataModel(0),
- dive(0),
- pInfo(0)
+ pInfoEntry(0),
+ pInfoNr(0)
{
height = 3;
QColor red(PERSIANRED1);
@@ -30,12 +30,19 @@ TankItem::TankItem(QObject *parent) :
trimixGradient.setColorAt(1.0, red);
trimix = trimixGradient;
air = blue;
+ memset(&diveCylinderStore, 0, sizeof(diveCylinderStore));
}
void TankItem::setData(DivePlotDataModel *model, struct plot_info *plotInfo, struct dive *d)
{
- pInfo = plotInfo;
- dive = d;
+ free(pInfoEntry);
+ // the plotInfo and dive structures passed in could become invalid before we stop using them,
+ // so copy the data that we need
+ int size = plotInfo->nr * sizeof(plotInfo->entry[0]);
+ pInfoEntry = (struct plot_data *)malloc(size);
+ pInfoNr = plotInfo->nr;
+ memcpy(pInfoEntry, plotInfo->entry, size);
+ copy_cylinders(d, &diveCylinderStore, false);
dataModel = model;
connect(dataModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(modelDataChanged(QModelIndex, QModelIndex)));
modelDataChanged();
@@ -65,7 +72,7 @@ void TankItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &b
{
// We don't have enougth data to calculate things, quit.
- if (!dive || !dataModel || !pInfo || !pInfo->nr)
+ if (!dataModel || !pInfoEntry || !pInfoNr)
return;
// remove the old rectangles
@@ -75,21 +82,21 @@ void TankItem::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &b
rects.clear();
// walk the list and figure out which tanks go where
- struct plot_data *entry = pInfo->entry;
+ struct plot_data *entry = pInfoEntry;
int cylIdx = entry->cylinderindex;
int i = -1;
int startTime = 0;
- struct gasmix *gas = &dive->cylinder[cylIdx].gasmix;
+ struct gasmix *gas = &diveCylinderStore.cylinder[cylIdx].gasmix;
qreal width, left;
- while (++i < pInfo->nr) {
- entry = &pInfo->entry[i];
+ while (++i < pInfoNr) {
+ entry = &pInfoEntry[i];
if (entry->cylinderindex == cylIdx)
continue;
width = hAxis->posAtValue(entry->sec) - hAxis->posAtValue(startTime);
left = hAxis->posAtValue(startTime);
createBar(left, width, gas);
cylIdx = entry->cylinderindex;
- gas = &dive->cylinder[cylIdx].gasmix;
+ gas = &diveCylinderStore.cylinder[cylIdx].gasmix;
startTime = entry->sec;
}
width = hAxis->posAtValue(entry->sec) - hAxis->posAtValue(startTime);
diff --git a/qt-ui/profile/tankitem.h b/qt-ui/profile/tankitem.h
index 615a7017d..f8d4ac9f8 100644
--- a/qt-ui/profile/tankitem.h
+++ b/qt-ui/profile/tankitem.h
@@ -28,8 +28,9 @@ private:
DivePlotDataModel *dataModel;
DiveCartesianAxis *hAxis;
int hDataColumn;
- struct dive *dive;
- struct plot_info *pInfo;
+ struct dive diveCylinderStore;
+ struct plot_data *pInfoEntry;
+ int pInfoNr;
qreal yPos, height;
QBrush air, nitrox, trimix;
QList<QGraphicsRectItem *> rects;