Bladeren bron

UI: Destroy the frontend API after OBS_FRONTEND_EVENT_EXIT

The frontend API was never explicitly cleaned up which has lead to
several crashes from plugins continuing to call it even after OBS itself
has been destroyed. We now destroy the API after the exit event, so
further calls by plugins will be no-ops instead of potentially accessing
destroyed OBS state.

This also required some changes to our own use of the API, as we relied
on the OBSBasic destructor to clean up some callbacks, by which point
the API should have already been destroyed.
Richard Stanway 2 jaren geleden
bovenliggende
commit
d997a56fb6
5 gewijzigde bestanden met toevoegingen van 11 en 9 verwijderingen
  1. 1 1
      UI/obs-frontend-api/obs-frontend-api.cpp
  2. 3 5
      UI/source-tree.cpp
  3. 0 1
      UI/source-tree.hpp
  4. 4 0
      UI/window-basic-main.cpp
  5. 3 2
      UI/window-basic-stats.cpp

+ 1 - 1
UI/obs-frontend-api/obs-frontend-api.cpp

@@ -13,7 +13,7 @@ void obs_frontend_set_callbacks_internal(obs_frontend_callbacks *callbacks)
 static inline bool callbacks_valid_(const char *func_name)
 {
 	if (!c) {
-		blog(LOG_WARNING, "Tried to call %s with no callbacks!",
+		blog(LOG_ERROR, "Tried to call %s with no callbacks!",
 		     func_name);
 		return false;
 	}

+ 3 - 5
UI/source-tree.cpp

@@ -640,6 +640,9 @@ void SourceTreeModel::OBSFrontendEvent(enum obs_frontend_event event, void *ptr)
 		stm->SceneChanged();
 		break;
 	case OBS_FRONTEND_EVENT_EXIT:
+		stm->Clear();
+		obs_frontend_remove_event_callback(OBSFrontendEvent, stm);
+		break;
 	case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CLEANUP:
 		stm->Clear();
 		break;
@@ -860,11 +863,6 @@ SourceTreeModel::SourceTreeModel(SourceTree *st_)
 	obs_frontend_add_event_callback(OBSFrontendEvent, this);
 }
 
-SourceTreeModel::~SourceTreeModel()
-{
-	obs_frontend_remove_event_callback(OBSFrontendEvent, this);
-}
-
 int SourceTreeModel::rowCount(const QModelIndex &parent) const
 {
 	return parent.isValid() ? 0 : items.count();

+ 0 - 1
UI/source-tree.hpp

@@ -132,7 +132,6 @@ class SourceTreeModel : public QAbstractListModel {
 
 public:
 	explicit SourceTreeModel(SourceTree *st);
-	~SourceTreeModel();
 
 	virtual int rowCount(const QModelIndex &parent) const override;
 	virtual QVariant data(const QModelIndex &index,

+ 4 - 0
UI/window-basic-main.cpp

@@ -5076,6 +5076,10 @@ void OBSBasic::closeEvent(QCloseEvent *event)
 	if (api)
 		api->on_event(OBS_FRONTEND_EVENT_EXIT);
 
+	// Destroys the frontend API so plugins can't continue calling it
+	obs_frontend_set_callbacks_internal(nullptr);
+	api = nullptr;
+
 	QMetaObject::invokeMethod(App(), "quit", Qt::QueuedConnection);
 }
 

+ 3 - 2
UI/window-basic-stats.cpp

@@ -29,6 +29,9 @@ void OBSBasicStats::OBSFrontendEvent(enum obs_frontend_event event, void *ptr)
 	case OBS_FRONTEND_EVENT_RECORDING_STOPPED:
 		stats->ResetRecTimeLeft();
 		break;
+	case OBS_FRONTEND_EVENT_EXIT:
+		obs_frontend_remove_event_callback(OBSFrontendEvent, stats);
+		break;
 	default:
 		break;
 	}
@@ -234,8 +237,6 @@ void OBSBasicStats::closeEvent(QCloseEvent *event)
 
 OBSBasicStats::~OBSBasicStats()
 {
-	obs_frontend_remove_event_callback(OBSFrontendEvent, this);
-
 	delete shortcutFilter;
 	os_cpu_usage_info_destroy(cpu_info);
 }