core: keep pw loop entered exactly when it is running

It is intended that the Pipewire loops are "entered" the whole time they
are running, i.e. are going to process further events. Currently we
enter/leave for single iterations, which is not right.

Fix by entering the loop on initial GSource idle callback, and leaving
at finalize.

That the loop has to be left from the same thread it was entered from is
a bit hard to do with GSources, as the finalize callback appears not
guaranteed to be called from any particular thread.  I didn't find a
fully general way to do this, so this puts additional constraints on how
WpLoopSource (and WpCore) are to be cleaned up.
This commit is contained in:
Pauli Virtanen
2024-04-14 12:36:58 +03:00
committed by George Kiagiadakis
parent e4f9fb824e
commit 7997fd490b

View File

@@ -30,20 +30,23 @@ struct _WpLoopSource
{
GSource parent;
struct pw_loop *loop;
gboolean entered;
};
static gboolean
wp_loop_source_dispatch (GSource * s, GSourceFunc callback, gpointer user_data)
{
WpLoopSource *ls = WP_LOOP_SOURCE (s);
int result;
wp_trace_boxed (G_TYPE_SOURCE, s, "entering pw main loop");
if (!ls->entered) {
wp_trace_boxed (G_TYPE_SOURCE, s, "entering pw main loop");
pw_loop_enter (ls->loop);
ls->entered = TRUE;
g_source_set_ready_time (s, -1);
}
pw_loop_enter (WP_LOOP_SOURCE(s)->loop);
result = pw_loop_iterate (WP_LOOP_SOURCE(s)->loop, 0);
pw_loop_leave (WP_LOOP_SOURCE(s)->loop);
wp_trace_boxed (G_TYPE_SOURCE, s, "leaving pw main loop");
result = pw_loop_iterate (ls->loop, 0);
if (G_UNLIKELY (result < 0))
wp_warning_boxed (G_TYPE_SOURCE, s,
@@ -55,7 +58,21 @@ wp_loop_source_dispatch (GSource * s, GSourceFunc callback, gpointer user_data)
static void
wp_loop_source_finalize (GSource * s)
{
pw_loop_destroy (WP_LOOP_SOURCE(s)->loop);
WpLoopSource *ls = WP_LOOP_SOURCE (s);
wp_trace_boxed (G_TYPE_SOURCE, s, "finalize loop source");
/* Source should be left from the thread it was entered from.
*
* This puts additional restrictions to upper layers on how WpLoopSource (and
* WpCore) can be used: they must be finalized from the GMainContext thread.
*/
if (ls->entered) {
wp_trace_boxed (G_TYPE_SOURCE, s, "leaving pw main loop");
pw_loop_leave (ls->loop);
}
pw_loop_destroy (ls->loop);
}
static GSourceFuncs source_funcs = {
@@ -75,6 +92,9 @@ wp_loop_source_new (void)
pw_loop_get_fd (WP_LOOP_SOURCE(s)->loop),
G_IO_IN | G_IO_ERR | G_IO_HUP);
/* dispatch immediately to enter the loop */
g_source_set_ready_time (s, 0);
return (GSource *) s;
}