weston-log: replace weston_log_ctx_compositor_destroy() by weston_log_ctx_destroy()

The function weston_log_ctx_compositor_destroy(), which destroys struct
weston_log_context, takes weston_compositor as argument. We may have a
weston_log_context unlinked from a weston_compositor and currently there
is no way to destroy it.

Add function weston_log_ctx_destroy(), what makes the destruction of
weston_log_context independent of weston_compositor.

With this change, one could destroy a weston_compositor and keep the
related weston_log_context (since now weston_log_context can be destroyed
without the need of a weston_compositor). But if weston_compositor gets
destroyed it's also necessary to destroy weston_log_context::global,
as the debug protocol depends on the compositor. So a listener has been
added to the destroy signal of weston_compositor.

Signed-off-by: Leandro Ribeiro <leandrohr@riseup.net>
diff --git a/libweston/weston-log.c b/libweston/weston-log.c
index 4cba0e8..43ca170 100644
--- a/libweston/weston-log.c
+++ b/libweston/weston-log.c
@@ -66,6 +66,7 @@
  */
 struct weston_log_context {
 	struct wl_global *global;
+	struct wl_listener compositor_destroy_listener;
 	struct wl_list scope_list; /**< weston_log_scope::compositor_link */
 	struct wl_list pending_subscription_list; /**< weston_log_subscription::source_link */
 };
@@ -398,6 +399,22 @@
 		weston_debug_v1_send_available(res, scope->name, scope->desc);
 }
 
+/** Disable debug-protocol
+ *
+ * @param log_ctx The log context where the debug-protocol is linked
+ *
+ * @ingroup internal-log
+ */
+static void
+weston_log_ctx_disable_debug_protocol(struct weston_log_context *log_ctx)
+{
+	if (!log_ctx->global)
+		return;
+
+	wl_global_destroy(log_ctx->global);
+	log_ctx->global = NULL;
+}
+
 /** Creates  weston_log_context structure
  *
  * \return NULL in case of failure, or a weston_log_context object in case of
@@ -418,27 +435,29 @@
 
 	wl_list_init(&log_ctx->scope_list);
 	wl_list_init(&log_ctx->pending_subscription_list);
+	wl_list_init(&log_ctx->compositor_destroy_listener.link);
 
 	return log_ctx;
 }
 
 /** Destroy weston_log_context structure
  *
- * \param compositor The libweston compositor whose weston-debug to tear down.
+ * \param log_ctx The log context to destroy.
  *
- * Clears weston_compositor::weston_log_ctx.
  * @ingroup log
  *
  */
 WL_EXPORT void
-weston_log_ctx_compositor_destroy(struct weston_compositor *compositor)
+weston_log_ctx_destroy(struct weston_log_context *log_ctx)
 {
-	struct weston_log_context *log_ctx = compositor->weston_log_ctx;
 	struct weston_log_scope *scope;
 	struct weston_log_subscription *pending_sub, *pending_sub_tmp;
 
-	if (log_ctx->global)
-		wl_global_destroy(log_ctx->global);
+	/* We can't destroy the log context if there's still a compositor
+	 * that depends on it. This is an user error */
+	 assert(wl_list_empty(&log_ctx->compositor_destroy_listener.link));
+
+	weston_log_ctx_disable_debug_protocol(log_ctx);
 
 	wl_list_for_each(scope, &log_ctx->scope_list, compositor_link)
 		fprintf(stderr, "Internal warning: debug scope '%s' has not been destroyed.\n",
@@ -456,8 +475,20 @@
 	/* pending_subscription_list should be empty at this point */
 
 	free(log_ctx);
+}
 
-	compositor->weston_log_ctx = NULL;
+static void
+compositor_destroy_listener(struct wl_listener *listener, void *data)
+{
+	struct weston_log_context *log_ctx =
+		wl_container_of(listener, log_ctx, compositor_destroy_listener);
+
+	/* We have to keep this list initalized as weston_log_ctx_destroy() has
+	 * to check if there's any compositor destroy listener registered */
+	wl_list_remove(&log_ctx->compositor_destroy_listener.link);
+	wl_list_init(&log_ctx->compositor_destroy_listener.link);
+
+	weston_log_ctx_disable_debug_protocol(log_ctx);
 }
 
 /** Enable weston-debug protocol extension
@@ -493,6 +524,9 @@
 	if (!log_ctx->global)
 		return;
 
+	log_ctx->compositor_destroy_listener.notify = compositor_destroy_listener;
+	wl_signal_add(&compositor->destroy_signal, &log_ctx->compositor_destroy_listener);
+
 	fprintf(stderr, "WARNING: debug protocol has been enabled. "
 		   "This is a potential denial-of-service attack vector and "
 		   "information leak.\n");