From 538b2f106de78b7dfeac2a98f3d5594ed0ed2ade Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 11 Jun 2012 13:44:19 -0400 Subject: [PATCH] gio: handle GSimpleAsyncResult errors in _finish vmethods Originally, the standard idiom with GSimpleAsyncResult was to handle all errors in the _finish wrapper function, so that vmethods only had to deal with successful results. But this means that chaining up to a parent _finish vmethod won't work correctly. Fix this by also checking for errors in all the relevant vmethods. (We have to redundantly check in both the vmethod and the wrapper to preserve compatibility.) https://bugzilla.gnome.org/show_bug.cgi?id=667375 https://bugzilla.gnome.org/show_bug.cgi?id=661767 --- gio/gasyncinitable.c | 19 ++++++++--------- gio/gbufferedinputstream.c | 3 +++ gio/gfile.c | 42 +++++++++++++++++++++++++++++++++++++- gio/gfileenumerator.c | 8 ++++++++ gio/gfileinputstream.c | 3 +++ gio/gfileoutputstream.c | 7 +++++-- gio/ginputstream.c | 12 +++++++++++ gio/giostream.c | 5 +++++ gio/gloadableicon.c | 3 +++ gio/goutputstream.c | 16 +++++++++++++++ 10 files changed, 104 insertions(+), 14 deletions(-) diff --git a/gio/gasyncinitable.c b/gio/gasyncinitable.c index 4d0c0978f..b13fac6f9 100644 --- a/gio/gasyncinitable.c +++ b/gio/gasyncinitable.c @@ -294,18 +294,15 @@ g_async_initable_real_init_finish (GAsyncInitable *initable, GAsyncResult *res, GError **error) { - /* Although g_async_initable_init_finish() does this error handling - * as well, we do it here too, so that a class that reimplements - * GAsyncInitable can properly run its parent class's implementation - * by directly invoking its ->init_async() and ->init_finish(). - */ - if (G_IS_SIMPLE_ASYNC_RESULT (res)) - { - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); - if (g_simple_async_result_propagate_error (simple, error)) - return FALSE; - } + GSimpleAsyncResult *simple; + g_return_val_if_fail (g_simple_async_result_is_valid (res, G_OBJECT (initable), + g_async_initable_real_init_async), + FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (res); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; return TRUE; } diff --git a/gio/gbufferedinputstream.c b/gio/gbufferedinputstream.c index 166bd414f..139199de9 100644 --- a/gio/gbufferedinputstream.c +++ b/gio/gbufferedinputstream.c @@ -1131,6 +1131,9 @@ g_buffered_input_stream_real_fill_finish (GBufferedInputStream *stream, simple = G_SIMPLE_ASYNC_RESULT (result); g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_buffered_input_stream_real_fill_async); + if (g_simple_async_result_propagate_error (simple, error)) + return -1; + nread = g_simple_async_result_get_op_res_gssize (simple); return nread; } diff --git a/gio/gfile.c b/gio/gfile.c index 3e44e4293..69f4100c6 100644 --- a/gio/gfile.c +++ b/gio/gfile.c @@ -4889,6 +4889,9 @@ g_file_real_query_info_finish (GFile *file, g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_query_info_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + data = g_simple_async_result_get_op_res_gpointer (simple); if (data->info) return g_object_ref (data->info); @@ -4960,6 +4963,9 @@ g_file_real_query_filesystem_info_finish (GFile *file, g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_query_filesystem_info_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + data = g_simple_async_result_get_op_res_gpointer (simple); if (data->info) return g_object_ref (data->info); @@ -5034,6 +5040,9 @@ g_file_real_enumerate_children_finish (GFile *file, g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_enumerate_children_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + data = g_simple_async_result_get_op_res_gpointer (simple); if (data->enumerator) return g_object_ref (data->enumerator); @@ -5096,6 +5105,9 @@ g_file_real_read_finish (GFile *file, g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_read_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + op = g_simple_async_result_get_op_res_gpointer (simple); if (op) return g_object_ref (op); @@ -5156,6 +5168,9 @@ g_file_real_append_to_finish (GFile *file, g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_append_to_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + op = g_simple_async_result_get_op_res_gpointer (simple); if (op) return g_object_ref (op); @@ -5216,6 +5231,9 @@ g_file_real_create_finish (GFile *file, g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_create_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + op = g_simple_async_result_get_op_res_gpointer (simple); if (op) return g_object_ref (op); @@ -5301,6 +5319,9 @@ g_file_real_replace_finish (GFile *file, g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_replace_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + data = g_simple_async_result_get_op_res_gpointer (simple); if (data->stream) return g_object_ref (data->stream); @@ -5363,6 +5384,9 @@ g_file_real_open_readwrite_finish (GFile *file, g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_open_readwrite_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + op = g_simple_async_result_get_op_res_gpointer (simple); if (op) return g_object_ref (op); @@ -5434,6 +5458,9 @@ g_file_real_create_readwrite_finish (GFile *file, g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_create_readwrite_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + op = g_simple_async_result_get_op_res_gpointer (simple); if (op) return g_object_ref (op); @@ -5519,6 +5546,9 @@ g_file_real_replace_readwrite_finish (GFile *file, g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_replace_readwrite_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + data = g_simple_async_result_get_op_res_gpointer (simple); if (data->stream) return g_object_ref (data->stream); @@ -5590,6 +5620,9 @@ g_file_real_set_display_name_finish (GFile *file, g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_set_display_name_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + data = g_simple_async_result_get_op_res_gpointer (simple); if (data->file) return g_object_ref (data->file); @@ -5717,6 +5750,9 @@ g_file_real_find_enclosing_mount_finish (GFile *file, g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_find_enclosing_mount_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + mount = g_simple_async_result_get_op_res_gpointer (simple); return g_object_ref (mount); } @@ -5840,7 +5876,11 @@ g_file_real_copy_finish (GFile *file, GAsyncResult *res, GError **error) { - /* Error handled in g_file_copy_finish() */ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + return TRUE; } diff --git a/gio/gfileenumerator.c b/gio/gfileenumerator.c index 654c69113..fa6863d41 100644 --- a/gio/gfileenumerator.c +++ b/gio/gfileenumerator.c @@ -693,6 +693,9 @@ g_file_enumerator_real_next_files_finish (GFileEnumerator *enumer g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_enumerator_real_next_files_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + op = g_simple_async_result_get_op_res_gpointer (simple); res = op->files; @@ -750,7 +753,12 @@ g_file_enumerator_real_close_finish (GFileEnumerator *enumerator, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_enumerator_real_close_async); + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + return TRUE; } diff --git a/gio/gfileinputstream.c b/gio/gfileinputstream.c index 61685432d..86d6d36b3 100644 --- a/gio/gfileinputstream.c +++ b/gio/gfileinputstream.c @@ -456,6 +456,9 @@ g_file_input_stream_real_query_info_finish (GFileInputStream *stream, g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_input_stream_real_query_info_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + data = g_simple_async_result_get_op_res_gpointer (simple); if (data->info) return g_object_ref (data->info); diff --git a/gio/gfileoutputstream.c b/gio/gfileoutputstream.c index ce09eb853..2670e0e61 100644 --- a/gio/gfileoutputstream.c +++ b/gio/gfileoutputstream.c @@ -551,14 +551,17 @@ g_file_output_stream_real_query_info_async (GFileOutputStream *stream, static GFileInfo * g_file_output_stream_real_query_info_finish (GFileOutputStream *stream, - GAsyncResult *res, - GError **error) + GAsyncResult *res, + GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); QueryInfoAsyncData *data; g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_output_stream_real_query_info_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + data = g_simple_async_result_get_op_res_gpointer (simple); if (data->info) return g_object_ref (data->info); diff --git a/gio/ginputstream.c b/gio/ginputstream.c index 8c61285c8..960811fd3 100644 --- a/gio/ginputstream.c +++ b/gio/ginputstream.c @@ -1227,6 +1227,9 @@ g_input_stream_real_read_finish (GInputStream *stream, g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_input_stream_real_read_async); + if (g_simple_async_result_propagate_error (simple, error)) + return -1; + op = g_simple_async_result_get_op_res_gpointer (simple); return op->count_read; @@ -1378,6 +1381,10 @@ g_input_stream_real_skip_finish (GInputStream *stream, SkipData *op; g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_input_stream_real_skip_async); + + if (g_simple_async_result_propagate_error (simple, error)) + return -1; + op = g_simple_async_result_get_op_res_gpointer (simple); return op->count_skipped; } @@ -1434,6 +1441,11 @@ g_input_stream_real_close_finish (GInputStream *stream, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_input_stream_real_close_async); + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + return TRUE; } diff --git a/gio/giostream.c b/gio/giostream.c index 593eedafd..e318c4a18 100644 --- a/gio/giostream.c +++ b/gio/giostream.c @@ -588,8 +588,13 @@ g_io_stream_real_close_finish (GIOStream *stream, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_io_stream_real_close_async); + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + return TRUE; } diff --git a/gio/gloadableicon.c b/gio/gloadableicon.c index 441eb1b88..66f97709f 100644 --- a/gio/gloadableicon.c +++ b/gio/gloadableicon.c @@ -229,6 +229,9 @@ g_loadable_icon_real_load_finish (GLoadableIcon *icon, g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_loadable_icon_real_load_async); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + data = g_simple_async_result_get_op_res_gpointer (simple); if (type) diff --git a/gio/goutputstream.c b/gio/goutputstream.c index 3ee4cf080..d512bbba0 100644 --- a/gio/goutputstream.c +++ b/gio/goutputstream.c @@ -1546,6 +1546,10 @@ g_output_stream_real_write_finish (GOutputStream *stream, WriteData *op; g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_output_stream_real_write_async); + + if (g_simple_async_result_propagate_error (simple, error)) + return -1; + op = g_simple_async_result_get_op_res_gpointer (simple); return op->count_written; } @@ -1613,6 +1617,10 @@ g_output_stream_real_splice_finish (GOutputStream *stream, SpliceData *op; g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_output_stream_real_splice_async); + + if (g_simple_async_result_propagate_error (simple, error)) + return -1; + op = g_simple_async_result_get_op_res_gpointer (simple); return op->bytes_copied; } @@ -1656,6 +1664,10 @@ g_output_stream_real_flush_finish (GOutputStream *stream, GAsyncResult *result, GError **error) { + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; return TRUE; } @@ -1720,6 +1732,10 @@ g_output_stream_real_close_finish (GOutputStream *stream, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_output_stream_real_close_async); + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; return TRUE; }