mirror of
https://github.com/epasveer/seer.git
synced 2026-08-29 08:34:42 +08:00
Fixed nasty segfault when removing items from scene.
This commit is contained in:
@@ -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 () {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user