Skip to content

Conversation

@dsaedtler
Copy link
Contributor

@dsaedtler dsaedtler commented Oct 23, 2025

Description

Makes some changes to how canvas removal is handled to avoid recursion in the middle of an erase() operation on the vector holding frontend-managed canvases.

Also prevents a similar issue when clearing scene data by replacing .clear() with a dedicated method that also ensures the canvas removal signal is properly fired for each removed canvas.

Motivation and Context

See #12728, which this PR superseedes.

How Has This Been Tested?

Reproduced using the following snipped (just added to the end of the OBSBasicSettings::OBSBasicSettings() constructor):

	obs_video_info ovi;
	obs_get_video_info(&ovi);
	OBSCanvasAutoRelease cv = obs_frontend_add_canvas("test", &ovi, PROGRAM);
	obs_frontend_remove_canvas(cv);
	OBSCanvasAutoRelease cv2 = obs_frontend_add_canvas("test2", &ovi, PROGRAM);

Note that the crash only happens in release builds, not debug.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • Tweak (non-breaking change to improve existing functionality)

Checklist:

  • My code has been run through clang-format.
  • I have read the contributing document.
  • My code is not on the master branch.
  • The code has been tested.
  • All commit messages are properly formatted and commits squashed where appropriate.
  • I have included updates to all appropriate documentation.

@WizardCM WizardCM added Bug Fix Non-breaking change which fixes an issue Enhancement Improvement to existing functionality labels Oct 25, 2025
@RytoEX RytoEX requested a review from PatTheMav October 30, 2025 17:18
@RytoEX RytoEX linked an issue Nov 4, 2025 that may be closed by this pull request
@RytoEX RytoEX added this to the OBS Studio 32.0 milestone Nov 5, 2025
@PatTheMav
Copy link
Member

Alright did a lot more debugging today and came up with this solution:

master...PatTheMav:obs-studio:canvas-memory-management-fix

Notes:

  • Fixes a potential crash in OBSStudioAPI::obs_frontend_add_canvas, as passing a nullptr as the const char *name will crash in the std::string constructor. It's always good practice not to trust any input sent via a public API and this one seems mandatory to me.
  • OBSStudioAPI::obs_frontend_add_canvas explicitly retains a reference to the canvas object while it is "shared" with the API client. This increments the actual reference count to at least "1".
  • OBSStudioAPI::obs_frontend_remove_canvas explicitly releases this shared reference once the API client requests its deletion. This should decrement the actual reference count to no less than "0".
  • Canvas::~Canvas is a "dumb" destructor now, much like Canvas::Canvas(obs_canvas_t *canvas) is a "dumb" constructor - neither bothers with reference counts or the lifetime of the pointer it holds.
  • OBSBasic (via OBSBasic::AddCanvas) is the initial owner (and creator) of the canvas object. Thus OBSBasic::RemoveCanvas needs to be the destructor of the same object. This requires an explicit call to obs_canvas_release to ensure that the implicit "0th" reference it created is released.
  • Similarly OBSBasic (via OBSBasic::LoadData and OBS::Canvas::LoadCanvases) is the initial owner (and indirect creator) of the canvas objects created from scene collection data. This requires OBSBasic::ClearSceneData to explicitly release the "0th" references it creates this way. This is potentially the most "confused" part of the current class implementation, but that's due to OBS::Canvas not being allowed to be the true owner of canvas objects (and instead is only created as a "dumb" wrapper around them).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Fix Non-breaking change which fixes an issue Enhancement Improvement to existing functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Segfault when switching from a SC with additional canvas

4 participants