Use weston_compositor_add_destroy_listener_once() in plugins

This introduces a new convention of checking through the compositor destroy
listener if the plugin is already initialized. If the plugin is already
initialized, then the plugin entry function succeeds as a no-op. This makes it
safe to load the same plugin multiple times in a running compositor.

Currently module loading functions return failure if a plugin is already
loaded, but that will change in the future. Therefore we need this other method
of ensuring we do not double-initialize a plugin which would lead to list
corruptions the very least.

All plugins are converted to use the new helper, except:
- those that do not have a destroy listener already, and
- hmi-controller which does the same open-coded as the common code pattern
  did not fit there.

Plugins should always have a compositor destroy listener registered since they
very least allocate a struct to hold their data. Hence omissions are
highlighted in code.

Backends do not need this because weston_compositor_load_backend() already
protects against double-init. GL-renderer does not export a standard module
init function so cannot be initialized the usual way and therefore is not
vulnerable to double-init.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
This commit is contained in:
Pekka Paalanen
2019-11-06 12:59:32 +02:00
committed by Daniel Stone
parent 5caef6d355
commit 6ffbba3ac1
15 changed files with 125 additions and 30 deletions
+35
View File
@@ -7639,6 +7639,41 @@ weston_load_module(const char *name, const char *entrypoint)
return init;
}
/** Add a compositor destroy listener only once
*
* \param compositor The compositor whose destroy to watch for.
* \param listener The listener struct to initialize.
* \param destroy_handler The callback when compositor is destroyed.
* \return True if listener is added, or false if there already is a listener
* with the given \c destroy_handler.
*
* This function does nothing and returns false if the given callback function
* is already present in the weston_compositor destroy callbacks list.
* Otherwise, this function initializes the given listener with the given
* callback pointer and adds it to the compositor's destroy callbacks list.
*
* This can be used to ensure that plugin initialization is done only once
* in case the same plugin is loaded multiple times. If this function returns
* false, the plugin should be already initialized successfully.
*
* All plugins should register a destroy listener for cleaning up. Note, that
* the plugin destruction order is not guaranteed: plugins that depend on other
* plugins must be able to be torn down in arbitrary order.
*
* \sa weston_compositor_tear_down, weston_compositor_destroy
*/
WL_EXPORT bool
weston_compositor_add_destroy_listener_once(struct weston_compositor *compositor,
struct wl_listener *listener,
wl_notify_func_t destroy_handler)
{
if (wl_signal_get(&compositor->destroy_signal, destroy_handler))
return false;
listener->notify = destroy_handler;
wl_signal_add(&compositor->destroy_signal, listener);
return true;
}
/** Tear down the compositor.
*