Skip to content

Commit a7f61cb

Browse files
committed
frontend: Fix recursion during canvas removal causing crashes
1 parent c025f21 commit a7f61cb

File tree

3 files changed

+21
-5
lines changed

3 files changed

+21
-5
lines changed

frontend/widgets/OBSBasic.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,7 @@ private slots:
11231123
std::vector<OBS::Canvas> canvases;
11241124

11251125
static void CanvasRemoved(void *data, calldata_t *params);
1126+
void ClearCanvases();
11261127

11271128
public:
11281129
const std::vector<OBS::Canvas> &GetCanvases() const noexcept { return canvases; }

frontend/widgets/OBSBasic_Canvases.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,30 @@ const OBS::Canvas &OBSBasic::AddCanvas(const std::string &name, obs_video_info *
3333

3434
bool OBSBasic::RemoveCanvas(OBSCanvas canvas)
3535
{
36+
bool removed = false;
3637
if (!canvas)
37-
return false;
38+
return removed;
3839

3940
auto canvas_it = std::find(std::begin(canvases), std::end(canvases), canvas);
4041
if (canvas_it != std::end(canvases)) {
42+
// Move canvas to a temporary object to delay removal of the canvas and calls to its signal handlers
43+
// until after erase() completes. This is to avoid issues with recursion coming from the
44+
// CanvasRemoved() signal handler.
45+
OBS::Canvas tmp = std::move(*canvas_it);
4146
canvases.erase(canvas_it);
42-
OnEvent(OBS_FRONTEND_EVENT_CANVAS_REMOVED);
43-
return true;
47+
removed = true;
4448
}
4549

46-
return false;
50+
if (removed)
51+
OnEvent(OBS_FRONTEND_EVENT_CANVAS_REMOVED);
52+
53+
return removed;
54+
}
55+
56+
void OBSBasic::ClearCanvases()
57+
{
58+
// Delete canvases one-by-one to ensure OBS_FRONTEND_EVENT_CANVAS_REMOVED is sent for each
59+
while (!canvases.empty()) {
60+
RemoveCanvas(OBSCanvas(canvases.back()));
61+
}
4762
}

frontend/widgets/OBSBasic_SceneCollections.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1539,7 +1539,7 @@ void OBSBasic::ClearSceneData()
15391539
obs_canvas_enum_scenes(canvas, cb, nullptr);
15401540
}
15411541

1542-
canvases.clear();
1542+
ClearCanvases();
15431543

15441544
OnEvent(OBS_FRONTEND_EVENT_SCENE_COLLECTION_CLEANUP);
15451545

0 commit comments

Comments
 (0)