Fixed nasty segfault when removing items from scene.

This commit is contained in:
Ernie Pasveer
2026-06-15 18:08:04 -05:00
parent 6dbd37b73c
commit 2c6bf5d56a
5 changed files with 54 additions and 1519 deletions
+1 -1
View File
@@ -3073,9 +3073,9 @@ void SeerGdbWidget::handleGdbParallelStacksVisualizer () {
w->show();
// Connect things.
QObject::connect(w, &SeerParallelStacksVisualizerWidget::refreshParallelStackFrames, this, &SeerGdbWidget::handleGdbParallelStackFrames);
QObject::connect(_gdbMonitor, &GdbMonitor::astrixTextOutput, w, &SeerParallelStacksVisualizerWidget::handleText);
QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, w, &SeerParallelStacksVisualizerWidget::handleText);
QObject::connect(w, &SeerParallelStacksVisualizerWidget::refreshParallelStackFrames, this, &SeerGdbWidget::handleGdbParallelStackFrames);
}
void SeerGdbWidget::handleGdbMonitor () {
+42 -6
View File
@@ -22,11 +22,22 @@ namespace Seer::PSV {
_headerLeft = QString("%1 Thread%2") .arg(stack.threadCount) .arg(stack.threadCount == 1 ? "" : "s");
if (!stack.threadIds.isEmpty()) {
QStringList ids = stack.threadIds;
if (ids.size() > 8)
_headerRight = QString("[%1 … +%2]") .arg(ids.mid(0, 8).join(", ")) .arg(ids.size() - 8);
else
_headerRight = "[" + ids.join(", ") + "]";
const QVector<QString> &ids = stack.threadIds;
const int shown = std::min<qsizetype>(ids.size(), 8);
QStringList parts;
parts.reserve(shown);
for (int i = 0; i < shown; ++i) {
parts.append(ids[i]);
}
if (ids.size() > 8) {
_headerRight = QString("[%1 … +%2]").arg(parts.join(", ")).arg(ids.size() - 8);
}else{
_headerRight = "[" + parts.join(", ") + "]";
}
}
for (int i = stack.functions.size() - 1; i >= 0; --i) {
@@ -51,6 +62,21 @@ namespace Seer::PSV {
_height = kPadY + kRowH * (1 + (int)_rows.size()) + kPadY;
}
StackBoxItem::~StackBoxItem() {
// Tell every edge that still points at us to forget about it.
// This must run BEFORE this object's memory is freed, regardless of
// whether the scene destroys this box or its edges first — it prevents
// the edges' own destructors (and any pending itemChange callbacks)
// from dereferencing a dangling pointer back to this item.
for (LiveEdge *e : _edges) {
e->detachEndpoint(this);
}
_edges.clear();
}
QRectF StackBoxItem::boundingRect() const {
return QRectF(0, 0, _width, _height);
}
@@ -174,11 +200,21 @@ namespace Seer::PSV {
}
LiveEdge::~LiveEdge() {
// Guard against half-destroyed scenes
// If our endpoints are still alive, tell them to forget about us so
// they don't later call update() on a dangling LiveEdge* during
// itemChange(). detachEndpoint() is a no-op if the endpoint has
// already nulled itself out via StackBoxItem::~StackBoxItem().
if (_from) _from->unregisterEdge(this);
if (_to) _to->unregisterEdge(this);
}
void LiveEdge::detachEndpoint(StackBoxItem *box) {
if (_from == box) _from = nullptr;
if (_to == box) _to = nullptr;
}
QRectF LiveEdge::boundingRect() const {
// Return the bounding rect of the two endpoints plus generous padding
+7
View File
@@ -21,6 +21,7 @@ namespace Seer::PSV {
public:
explicit StackBoxItem(const Stack& stack, QGraphicsItem* parent = nullptr);
~StackBoxItem() override;
QRectF boundingRect () const override;
void paint (QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
@@ -77,6 +78,12 @@ namespace Seer::PSV {
QRectF boundingRect () const override;
void paint (QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
// Called by StackBoxItem's destructor so this edge stops referencing
// an endpoint that is about to be (or has been) destroyed. After this,
// the edge renders nothing and its own destructor won't touch `box`.
void detachEndpoint (StackBoxItem* box);
private:
StackBoxItem* _from; // child (bottom anchor)
StackBoxItem* _to; // parent (top anchor)
@@ -42,6 +42,10 @@ SeerParallelStacksVisualizerWidget::SeerParallelStacksVisualizerWidget (QWidget*
}
SeerParallelStacksVisualizerWidget::~SeerParallelStacksVisualizerWidget () {
if (QGraphicsScene* scene = graphicsView->scene()) {
scene->clear();
}
}
void SeerParallelStacksVisualizerWidget::handleText (const QString& text) {
-1512
View File
File diff suppressed because it is too large Load Diff