fix some more leaks

This commit is contained in:
Wim Taymans 2015-08-26 17:11:10 +02:00
parent 78a7a1ea72
commit eada50916a
4 changed files with 97 additions and 54 deletions

View file

@ -137,6 +137,8 @@ pinos_context_finalize (GObject * object)
PinosContext *context = PINOS_CONTEXT (object); PinosContext *context = PINOS_CONTEXT (object);
PinosContextPrivate *priv = context->priv; PinosContextPrivate *priv = context->priv;
g_debug ("free context %p", context);
if (priv->id) if (priv->id)
g_bus_unwatch_name(priv->id); g_bus_unwatch_name(priv->id);
@ -145,6 +147,9 @@ pinos_context_finalize (GObject * object)
if (priv->properties) if (priv->properties)
pinos_properties_free (priv->properties); pinos_properties_free (priv->properties);
g_list_free (priv->sources);
g_list_free (priv->clients);
g_list_free (priv->source_outputs);
g_clear_object (&priv->subscribe); g_clear_object (&priv->subscribe);
g_clear_error (&priv->error); g_clear_error (&priv->error);
@ -272,11 +277,22 @@ pinos_context_init (PinosContext * context)
{ {
PinosContextPrivate *priv = context->priv = PINOS_CONTEXT_GET_PRIVATE (context); PinosContextPrivate *priv = context->priv = PINOS_CONTEXT_GET_PRIVATE (context);
g_debug ("new context %p", context);
priv->state = PINOS_CONTEXT_STATE_UNCONNECTED; priv->state = PINOS_CONTEXT_STATE_UNCONNECTED;
priv->subscribe = pinos_subscribe_new (); priv->subscribe = pinos_subscribe_new ();
g_object_set (priv->subscribe, "subscription-mask", PINOS_SUBSCRIPTION_FLAGS_ALL, NULL); g_object_set (priv->subscribe,
g_signal_connect (priv->subscribe, "subscription-event", (GCallback) subscription_cb, context); "subscription-mask", PINOS_SUBSCRIPTION_FLAGS_ALL,
g_signal_connect (priv->subscribe, "notify::state", (GCallback) subscription_state, context); NULL);
g_signal_connect (priv->subscribe,
"subscription-event",
(GCallback) subscription_cb,
context);
g_signal_connect (priv->subscribe,
"notify::state",
(GCallback) subscription_state,
context);
} }
/** /**
@ -324,13 +340,21 @@ do_notify_state (PinosContext *context)
static void static void
context_set_state (PinosContext *context, context_set_state (PinosContext *context,
PinosContextState state) PinosContextState state,
GError *error)
{ {
if (context->priv->state != state) { if (context->priv->state != state) {
if (error) {
g_clear_error (&context->priv->error);
context->priv->error = error;
}
context->priv->state = state; context->priv->state = state;
g_main_context_invoke (context->priv->context, g_main_context_invoke (context->priv->context,
(GSourceFunc) do_notify_state, (GSourceFunc) do_notify_state,
g_object_ref (context)); g_object_ref (context));
} else {
if (error)
g_error_free (error);
} }
} }
static void static void
@ -348,15 +372,14 @@ on_client_proxy (GObject *source_object,
if (priv->client == NULL) if (priv->client == NULL)
goto client_failed; goto client_failed;
context_set_state (context, PINOS_CONTEXT_STATE_READY); context_set_state (context, PINOS_CONTEXT_STATE_READY, NULL);
return; return;
client_failed: client_failed:
{ {
priv->error = error;
context_set_state (context, PINOS_STREAM_STATE_ERROR);
g_warning ("failed to get client proxy: %s", error->message); g_warning ("failed to get client proxy: %s", error->message);
context_set_state (context, PINOS_STREAM_STATE_ERROR, error);
return; return;
} }
} }
@ -375,8 +398,7 @@ on_client_connected (GObject *source_object,
ret = g_dbus_proxy_call_finish (priv->daemon, res, &error); ret = g_dbus_proxy_call_finish (priv->daemon, res, &error);
if (ret == NULL) { if (ret == NULL) {
g_warning ("failed to connect client: %s", error->message); g_warning ("failed to connect client: %s", error->message);
priv->error = error; context_set_state (context, PINOS_CONTEXT_STATE_ERROR, error);
context_set_state (context, PINOS_CONTEXT_STATE_ERROR);
return; return;
} }
@ -401,7 +423,7 @@ on_daemon_connected (GObject *source_object,
PinosContextPrivate *priv = context->priv; PinosContextPrivate *priv = context->priv;
GVariant *variant; GVariant *variant;
context_set_state (context, PINOS_CONTEXT_STATE_REGISTERING); context_set_state (context, PINOS_CONTEXT_STATE_REGISTERING, NULL);
variant = pinos_properties_to_variant (priv->properties); variant = pinos_properties_to_variant (priv->properties);
@ -436,9 +458,12 @@ subscription_cb (PinosSubscribe *subscribe,
} else if (event == PINOS_SUBSCRIPTION_EVENT_REMOVE) { } else if (event == PINOS_SUBSCRIPTION_EVENT_REMOVE) {
priv->clients = g_list_remove (priv->clients, object); priv->clients = g_list_remove (priv->clients, object);
if (object == priv->client) { if (object == priv->client && !priv->disconnecting) {
priv->error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CLOSED, "Client disappeared"); context_set_state (context,
context_set_state (context, PINOS_CONTEXT_STATE_ERROR); PINOS_CONTEXT_STATE_ERROR,
g_error_new_literal (G_IO_ERROR,
G_IO_ERROR_CLOSED,
"Client disappeared"));
} }
} }
break; break;
@ -520,10 +545,13 @@ on_name_vanished (GDBusConnection *connection,
g_object_set (priv->subscribe, "connection", connection, NULL); g_object_set (priv->subscribe, "connection", connection, NULL);
if (priv->flags & PINOS_CONTEXT_FLAGS_NOFAIL) { if (priv->flags & PINOS_CONTEXT_FLAGS_NOFAIL) {
context_set_state (context, PINOS_CONTEXT_STATE_CONNECTING); context_set_state (context, PINOS_CONTEXT_STATE_CONNECTING, NULL);
} else { } else {
priv->error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CLOSED, "Connection closed"); context_set_state (context,
context_set_state (context, PINOS_CONTEXT_STATE_ERROR); PINOS_CONTEXT_STATE_ERROR,
g_error_new_literal (G_IO_ERROR,
G_IO_ERROR_CLOSED,
"Connection closed"));
} }
} }
@ -571,7 +599,7 @@ pinos_context_connect (PinosContext *context,
priv->flags = flags; priv->flags = flags;
context_set_state (context, PINOS_CONTEXT_STATE_CONNECTING); context_set_state (context, PINOS_CONTEXT_STATE_CONNECTING, NULL);
g_main_context_invoke (priv->context, g_main_context_invoke (priv->context,
(GSourceFunc) do_connect, (GSourceFunc) do_connect,
g_object_ref (context)); g_object_ref (context));
@ -591,7 +619,7 @@ finish_client_disconnect (PinosContext *context)
priv->id = 0; priv->id = 0;
} }
context_set_state (context, PINOS_CONTEXT_STATE_UNCONNECTED); context_set_state (context, PINOS_CONTEXT_STATE_UNCONNECTED, NULL);
} }
static void static void
@ -604,11 +632,12 @@ on_client_disconnected (GObject *source_object,
GError *error = NULL; GError *error = NULL;
GVariant *ret; GVariant *ret;
priv->disconnecting = FALSE;
ret = g_dbus_proxy_call_finish (priv->client, res, &error); ret = g_dbus_proxy_call_finish (priv->client, res, &error);
if (ret == NULL) { if (ret == NULL) {
g_warning ("failed to disconnect client: %s", error->message); g_warning ("failed to disconnect client: %s", error->message);
priv->error = error; context_set_state (context, PINOS_CONTEXT_STATE_ERROR, error);
context_set_state (context, PINOS_CONTEXT_STATE_ERROR);
g_object_unref (context); g_object_unref (context);
return; return;
} }
@ -651,12 +680,15 @@ pinos_context_disconnect (PinosContext *context)
g_return_val_if_fail (PINOS_IS_CONTEXT (context), FALSE); g_return_val_if_fail (PINOS_IS_CONTEXT (context), FALSE);
priv = context->priv; priv = context->priv;
g_return_val_if_fail (!priv->disconnecting, FALSE);
if (priv->client == NULL) { if (priv->client == NULL) {
finish_client_disconnect (context); finish_client_disconnect (context);
return TRUE; return TRUE;
} }
priv->disconnecting = TRUE;
g_main_context_invoke (priv->context, g_main_context_invoke (priv->context,
(GSourceFunc) do_disconnect, (GSourceFunc) do_disconnect,
g_object_ref (context)); g_object_ref (context));

View file

@ -34,6 +34,7 @@ struct _PinosContextPrivate
GDBusProxy *daemon; GDBusProxy *daemon;
GDBusProxy *client; GDBusProxy *client;
gboolean disconnecting;
PinosSubscriptionFlags subscription_mask; PinosSubscriptionFlags subscription_mask;
PinosSubscribe *subscribe; PinosSubscribe *subscribe;
@ -56,8 +57,8 @@ GDBusProxy * pinos_subscribe_get_proxy_finish (PinosSubscribe *subsc
typedef struct { typedef struct {
guint32 version;
PinosBufferHeader header; PinosBufferHeader header;
guint32 version;
guint32 length; guint32 length;
} PinosStackHeader; } PinosStackHeader;

View file

@ -165,13 +165,21 @@ do_notify_state (PinosStream *stream)
static void static void
stream_set_state (PinosStream *stream, stream_set_state (PinosStream *stream,
PinosStreamState state) PinosStreamState state,
GError *error)
{ {
if (stream->priv->state != state) { if (stream->priv->state != state) {
if (error) {
g_clear_error (&stream->priv->error);
stream->priv->error = error;
}
stream->priv->state = state; stream->priv->state = state;
g_main_context_invoke (stream->priv->context->priv->context, g_main_context_invoke (stream->priv->context->priv->context,
(GSourceFunc) do_notify_state, (GSourceFunc) do_notify_state,
g_object_ref (stream)); g_object_ref (stream));
} else {
if (error)
g_error_free (error);
} }
} }
@ -189,8 +197,11 @@ subscription_cb (PinosSubscribe *subscribe,
case PINOS_SUBSCRIPTION_FLAG_SOURCE_OUTPUT: case PINOS_SUBSCRIPTION_FLAG_SOURCE_OUTPUT:
if (event == PINOS_SUBSCRIPTION_EVENT_REMOVE) { if (event == PINOS_SUBSCRIPTION_EVENT_REMOVE) {
if (object == priv->source_output && !priv->disconnecting) { if (object == priv->source_output && !priv->disconnecting) {
priv->error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CLOSED, "output disappeared"); stream_set_state (stream,
stream_set_state (stream, PINOS_STREAM_STATE_ERROR); PINOS_STREAM_STATE_ERROR,
g_error_new_literal (G_IO_ERROR,
G_IO_ERROR_CLOSED,
"Output disappeared"));
} }
} }
break; break;
@ -220,6 +231,9 @@ pinos_stream_finalize (GObject * object)
PinosStream *stream = PINOS_STREAM (object); PinosStream *stream = PINOS_STREAM (object);
PinosStreamPrivate *priv = stream->priv; PinosStreamPrivate *priv = stream->priv;
g_debug ("free stream %p", stream);
g_clear_object (&priv->socket);
g_clear_object (&priv->source_output); g_clear_object (&priv->source_output);
if (priv->possible_formats) if (priv->possible_formats)
@ -383,6 +397,8 @@ pinos_stream_init (PinosStream * stream)
{ {
PinosStreamPrivate *priv = stream->priv = PINOS_STREAM_GET_PRIVATE (stream); PinosStreamPrivate *priv = stream->priv = PINOS_STREAM_GET_PRIVATE (stream);
g_debug ("new stream %p", stream);
priv->state = PINOS_STREAM_STATE_UNCONNECTED; priv->state = PINOS_STREAM_STATE_UNCONNECTED;
} }
@ -495,16 +511,15 @@ on_source_output_proxy (GObject *source_object,
g_object_notify (G_OBJECT (stream), "properties"); g_object_notify (G_OBJECT (stream), "properties");
} }
stream_set_state (stream, PINOS_STREAM_STATE_READY); stream_set_state (stream, PINOS_STREAM_STATE_READY, NULL);
g_object_unref (stream); g_object_unref (stream);
return; return;
source_output_failed: source_output_failed:
{ {
priv->error = error;
stream_set_state (stream, PINOS_STREAM_STATE_ERROR);
g_warning ("failed to get source output proxy: %s", error->message); g_warning ("failed to get source output proxy: %s", error->message);
stream_set_state (stream, PINOS_STREAM_STATE_ERROR, error);
g_object_unref (stream); g_object_unref (stream);
return; return;
} }
@ -528,7 +543,7 @@ on_source_output_created (GObject *source_object,
if (ret == NULL) if (ret == NULL)
goto create_failed; goto create_failed;
g_variant_get (ret, "(o)", &source_output_path); g_variant_get (ret, "(&o)", &source_output_path);
pinos_subscribe_get_proxy (context->priv->subscribe, pinos_subscribe_get_proxy (context->priv->subscribe,
PINOS_DBUS_SERVICE, PINOS_DBUS_SERVICE,
@ -544,9 +559,8 @@ on_source_output_created (GObject *source_object,
/* ERRORS */ /* ERRORS */
create_failed: create_failed:
{ {
priv->error = error;
stream_set_state (stream, PINOS_STREAM_STATE_ERROR);
g_warning ("failed to get connect capture: %s", error->message); g_warning ("failed to get connect capture: %s", error->message);
stream_set_state (stream, PINOS_STREAM_STATE_ERROR, error);
g_object_unref (stream); g_object_unref (stream);
return; return;
} }
@ -608,7 +622,7 @@ pinos_stream_connect_capture (PinosStream *stream,
priv->accepted_formats = accepted_formats; priv->accepted_formats = accepted_formats;
priv->provide = FALSE; priv->provide = FALSE;
stream_set_state (stream, PINOS_STREAM_STATE_CONNECTING); stream_set_state (stream, PINOS_STREAM_STATE_CONNECTING, NULL);
g_main_context_invoke (context->priv->context, g_main_context_invoke (context->priv->context,
(GSourceFunc) do_connect_capture, (GSourceFunc) do_connect_capture,
@ -667,7 +681,7 @@ pinos_stream_connect_provide (PinosStream *stream,
priv->possible_formats = possible_formats; priv->possible_formats = possible_formats;
priv->provide = TRUE; priv->provide = TRUE;
stream_set_state (stream, PINOS_STREAM_STATE_CONNECTING); stream_set_state (stream, PINOS_STREAM_STATE_CONNECTING, NULL);
g_main_context_invoke (context->priv->context, g_main_context_invoke (context->priv->context,
(GSourceFunc) do_connect_provide, (GSourceFunc) do_connect_provide,
@ -695,16 +709,17 @@ on_source_output_removed (GObject *source_object,
if (ret == NULL) if (ret == NULL)
goto proxy_failed; goto proxy_failed;
stream_set_state (stream, PINOS_STREAM_STATE_UNCONNECTED); g_variant_unref (ret);
stream_set_state (stream, PINOS_STREAM_STATE_UNCONNECTED, NULL);
g_object_unref (stream); g_object_unref (stream);
return; return;
/* ERRORS */ /* ERRORS */
proxy_failed: proxy_failed:
{ {
priv->error = error;
stream_set_state (stream, PINOS_STREAM_STATE_ERROR);
g_warning ("failed to disconnect: %s", error->message); g_warning ("failed to disconnect: %s", error->message);
stream_set_state (stream, PINOS_STREAM_STATE_ERROR, error);
g_object_unref (stream); g_object_unref (stream);
return; return;
} }
@ -887,9 +902,8 @@ handle_socket (PinosStream *stream, gint fd)
/* ERRORS */ /* ERRORS */
socket_failed: socket_failed:
{ {
priv->error = error;
stream_set_state (stream, PINOS_STREAM_STATE_ERROR);
g_warning ("failed to create socket: %s", error->message); g_warning ("failed to create socket: %s", error->message);
stream_set_state (stream, PINOS_STREAM_STATE_ERROR, error);
return; return;
} }
} }
@ -960,9 +974,11 @@ on_stream_started (GObject *source_object,
if ((fd = g_unix_fd_list_get (out_fd_list, fd_idx, &error)) < 0) if ((fd = g_unix_fd_list_get (out_fd_list, fd_idx, &error)) < 0)
goto fd_failed; goto fd_failed;
g_object_unref (out_fd_list);
handle_socket (stream, fd); handle_socket (stream, fd);
stream_set_state (stream, PINOS_STREAM_STATE_STREAMING); stream_set_state (stream, PINOS_STREAM_STATE_STREAMING, NULL);
return; return;
@ -975,12 +991,12 @@ start_failed:
fd_failed: fd_failed:
{ {
g_warning ("failed to get FD: %s", error->message); g_warning ("failed to get FD: %s", error->message);
g_object_unref (out_fd_list);
goto exit_error; goto exit_error;
} }
exit_error: exit_error:
{ {
priv->error = error; stream_set_state (stream, PINOS_STREAM_STATE_ERROR, error);
stream_set_state (stream, PINOS_STREAM_STATE_ERROR);
return; return;
} }
} }
@ -1034,7 +1050,7 @@ pinos_stream_start (PinosStream *stream,
priv->mode = mode; priv->mode = mode;
priv->format = format; priv->format = format;
stream_set_state (stream, PINOS_STREAM_STATE_STARTING); stream_set_state (stream, PINOS_STREAM_STATE_STARTING, NULL);
g_main_context_invoke (priv->context->priv->context, (GSourceFunc) do_start, stream); g_main_context_invoke (priv->context->priv->context, (GSourceFunc) do_start, stream);
@ -1061,16 +1077,15 @@ on_stream_stopped (GObject *source_object,
g_clear_pointer (&priv->format, g_free); g_clear_pointer (&priv->format, g_free);
g_object_notify (G_OBJECT (stream), "format"); g_object_notify (G_OBJECT (stream), "format");
stream_set_state (stream, PINOS_STREAM_STATE_READY); stream_set_state (stream, PINOS_STREAM_STATE_READY, NULL);
return; return;
/* ERRORS */ /* ERRORS */
call_failed: call_failed:
{ {
priv->error = error;
stream_set_state (stream, PINOS_STREAM_STATE_ERROR);
g_warning ("failed to release: %s", error->message); g_warning ("failed to release: %s", error->message);
stream_set_state (stream, PINOS_STREAM_STATE_ERROR, error);
return; return;
} }
} }
@ -1223,11 +1238,6 @@ pinos_stream_provide_buffer (PinosStream *stream,
flags, flags,
NULL, NULL,
&error); &error);
if (sb->message) {
g_object_unref (sb->message);
sb->message = NULL;
}
if (len == -1) if (len == -1)
goto send_error; goto send_error;
@ -1237,9 +1247,8 @@ pinos_stream_provide_buffer (PinosStream *stream,
send_error: send_error:
{ {
priv->error = error;
stream_set_state (stream, PINOS_STREAM_STATE_ERROR);
g_warning ("failed to send_message: %s", error->message); g_warning ("failed to send_message: %s", error->message);
stream_set_state (stream, PINOS_STREAM_STATE_ERROR, error);
return FALSE; return FALSE;
} }
} }

View file

@ -244,7 +244,7 @@ on_stream_notify (GObject *gobject,
GstPinosSink *pinossink = user_data; GstPinosSink *pinossink = user_data;
state = pinos_stream_get_state (stream); state = pinos_stream_get_state (stream);
GST_DEBUG ("got stream state %d\n", state); GST_DEBUG ("got stream state %d", state);
switch (state) { switch (state) {
case PINOS_STREAM_STATE_UNCONNECTED: case PINOS_STREAM_STATE_UNCONNECTED:
@ -394,6 +394,7 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
if (pinos_stream_get_state (pinossink->stream) != PINOS_STREAM_STATE_STREAMING) if (pinos_stream_get_state (pinossink->stream) != PINOS_STREAM_STATE_STREAMING)
goto streaming_error; goto streaming_error;
pinos_stream_provide_buffer (pinossink->stream, &pbuf); pinos_stream_provide_buffer (pinossink->stream, &pbuf);
pinos_buffer_clear (&pbuf);
pinos_main_loop_unlock (pinossink->loop); pinos_main_loop_unlock (pinossink->loop);
return GST_FLOW_OK; return GST_FLOW_OK;
@ -452,7 +453,7 @@ on_context_notify (GObject *gobject,
PinosContextState state; PinosContextState state;
state = pinos_context_get_state (ctx); state = pinos_context_get_state (ctx);
GST_DEBUG ("got context state %d\n", state); GST_DEBUG ("got context state %d", state);
switch (state) { switch (state) {
case PINOS_CONTEXT_STATE_UNCONNECTED: case PINOS_CONTEXT_STATE_UNCONNECTED:
@ -475,7 +476,7 @@ gst_pinos_sink_open (GstPinosSink * pinossink)
GError *error = NULL; GError *error = NULL;
pinossink->context = g_main_context_new (); pinossink->context = g_main_context_new ();
GST_DEBUG ("context %p\n", pinossink->context); GST_DEBUG ("context %p", pinossink->context);
pinossink->loop = pinos_main_loop_new (pinossink->context, "pinos-sink-loop"); pinossink->loop = pinos_main_loop_new (pinossink->context, "pinos-sink-loop");
if (!pinos_main_loop_start (pinossink->loop, &error)) if (!pinos_main_loop_start (pinossink->loop, &error))