On Thu, Feb 20, 2014 at 03:57:00PM +0100, Pavel Hrdina wrote:
On 20.2.2014 15:07, Christophe Fergeau wrote:
>>@@ -102,17 +102,33 @@ static GOutputStream*
gvir_stream_get_output_stream(GIOStream *io_stream)
>>
>> static gboolean gvir_stream_close(GIOStream *io_stream,
>> GCancellable *cancellable,
>>- G_GNUC_UNUSED GError **error)
>>+ GError **error)
>> {
>> GVirStream *self = GVIR_STREAM(io_stream);
>>+ GError *local_error = NULL;
>>+ gboolean i_ret = TRUE, o_ret = TRUE;
>>
>> if (self->priv->input_stream)
>>- g_input_stream_close(self->priv->input_stream, cancellable,
NULL);
>>+ i_ret = g_input_stream_close(self->priv->input_stream,
cancellable, &local_error);
>>+
>>+ if (local_error) {
>>+ if (!*error)
>>+ g_propagate_error(error, local_error);
>>+ else
>>+ g_error_free(local_error);
>>+ }
>
>g_propagate_error will be doing this if (!*error) check for you, so this
>can be written as
>if (local_error)
> g_propagate_error(error, local_error);
>
>
>
>void g_propagate_error (GError **dest,
> GError *src);
>If dest is NULL, free src; otherwise, moves src into *dest.
>
>
>Christophe
>
The g_propagate_error will free the src only if error == NULL but if
the *error is not NULL it will print warning and do nothing with the
src and therefore there could be memory leak. That's why I'm checking
if *error is null and otherwise I'll free the local_error.
If error is NULL, this test will cause a NULL pointer dereference.
Passing a GError ** pointing to a non-NULL GError is a programming error,
so what is done in other places in libvirt-glib is to have a
g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
at the beginning of the function to reject such invalid calls right away at
runtime.
If you do that, the first check and g_error_free() can be removed.
If an error occurred there, and if the g_output_stream_close() call fails,
we'll be in a situation when g_propagate_error() can try to overwrite an
already set error. g_io_stream_close() says "On failure the first error
that happened will be reported, but the close operation will finish as much
as possible." so we need to do the g_output_stream_close() call even if the
g_input_stream_close() call failed, but not try to set the error when this
happened.
Christophe