diff --git a/0001-curl-Also-map-HTTP-errors-for-retries.patch b/0001-curl-Also-map-HTTP-errors-for-retries.patch new file mode 100644 index 0000000..aa82d78 --- /dev/null +++ b/0001-curl-Also-map-HTTP-errors-for-retries.patch @@ -0,0 +1,132 @@ +From 76ab8621887f1499deb067982dd512acdf99538b Mon Sep 17 00:00:00 2001 +From: Colin Walters +Date: Fri, 15 Mar 2024 18:41:02 -0400 +Subject: [PATCH] curl: Also map HTTP errors for retries + +When we added the retry logic, the intention here was definitely +to do it not just for network errors but also e.g. HTTP 500s and +the like. + +xref https://pagure.io/releng/issue/11439 +where we rather painfully debugged that this was missing. +--- + src/libostree/ostree-fetcher-curl.c | 18 +++++++++--------- + src/libostree/ostree-fetcher-soup.c | 2 +- + src/libostree/ostree-fetcher-soup3.c | 2 +- + src/libostree/ostree-fetcher-util.c | 7 ++++--- + src/libostree/ostree-fetcher-util.h | 2 +- + 5 files changed, 16 insertions(+), 15 deletions(-) + +diff --git a/src/libostree/ostree-fetcher-curl.c b/src/libostree/ostree-fetcher-curl.c +index e9b9672b..d6902893 100644 +--- a/src/libostree/ostree-fetcher-curl.c ++++ b/src/libostree/ostree-fetcher-curl.c +@@ -322,6 +322,8 @@ check_multi_info (OstreeFetcher *fetcher) + + req = g_task_get_task_data (task); + ++ gboolean retry_all = (!is_file && req->fetcher->opt_retry_all); ++ + if (req->caught_write_error) + g_task_return_error (task, g_steal_pointer (&req->caught_write_error)); + else if (curlres != CURLE_OK) +@@ -337,12 +339,9 @@ check_multi_info (OstreeFetcher *fetcher) + /* When it is not a file, we want to retry the request. + * We accomplish that by using G_IO_ERROR_TIMED_OUT. + */ +- gboolean opt_retry_all = req->fetcher->opt_retry_all; +- int g_io_error_code +- = (is_file || !opt_retry_all) ? G_IO_ERROR_FAILED : G_IO_ERROR_TIMED_OUT; +- g_task_return_new_error (task, G_IO_ERROR, g_io_error_code, +- "While fetching %s: [%u] %s", eff_url, curlres, +- curl_easy_strerror (curlres)); ++ g_task_return_new_error ( ++ task, G_IO_ERROR, retry_all ? G_IO_ERROR_TIMED_OUT : G_IO_ERROR, ++ "While fetching %s: [%u] %s", eff_url, curlres, curl_easy_strerror (curlres)); + _ostree_fetcher_journal_failure (req->fetcher->remote_name, eff_url, + curl_easy_strerror (curlres)); + } +@@ -362,12 +361,13 @@ check_multi_info (OstreeFetcher *fetcher) + + if (!is_file && !(response >= 200 && response < 300) && response != 304) + { +- GIOErrorEnum giocode = _ostree_fetcher_http_status_code_to_io_error (response); ++ GIOErrorEnum giocode ++ = _ostree_fetcher_http_status_code_to_io_error (response, retry_all); + + if (req->idx + 1 == req->mirrorlist->len) + { +- g_autofree char *response_msg +- = g_strdup_printf ("Server returned HTTP %lu", response); ++ g_autofree char *response_msg = g_strdup_printf ( ++ "While fetching %s: Server returned HTTP %lu", eff_url, response); + g_task_return_new_error (task, G_IO_ERROR, giocode, "%s", response_msg); + if (req->fetcher->remote_name + && !((req->flags & OSTREE_FETCHER_REQUEST_OPTIONAL_CONTENT) > 0 +diff --git a/src/libostree/ostree-fetcher-soup.c b/src/libostree/ostree-fetcher-soup.c +index e75e72bf..b68c4fd1 100644 +--- a/src/libostree/ostree-fetcher-soup.c ++++ b/src/libostree/ostree-fetcher-soup.c +@@ -1094,7 +1094,7 @@ on_request_sent (GObject *object, GAsyncResult *result, gpointer user_data) + #endif + break; + default: +- code = _ostree_fetcher_http_status_code_to_io_error (msg->status_code); ++ code = _ostree_fetcher_http_status_code_to_io_error (msg->status_code, FALSE); + break; + } + +diff --git a/src/libostree/ostree-fetcher-soup3.c b/src/libostree/ostree-fetcher-soup3.c +index 6de5c1ed..fa71b363 100644 +--- a/src/libostree/ostree-fetcher-soup3.c ++++ b/src/libostree/ostree-fetcher-soup3.c +@@ -621,7 +621,7 @@ on_request_sent (GObject *object, GAsyncResult *result, gpointer user_data) + { + g_autofree char *uristring + = g_uri_to_string (soup_message_get_uri (request->message)); +- GIOErrorEnum code = _ostree_fetcher_http_status_code_to_io_error (status); ++ GIOErrorEnum code = _ostree_fetcher_http_status_code_to_io_error (status, FALSE); + { + g_autofree char *errmsg = g_strdup_printf ("Server returned status %u: %s", status, + soup_status_get_phrase (status)); +diff --git a/src/libostree/ostree-fetcher-util.c b/src/libostree/ostree-fetcher-util.c +index b797bee7..7ca9f07d 100644 +--- a/src/libostree/ostree-fetcher-util.c ++++ b/src/libostree/ostree-fetcher-util.c +@@ -224,7 +224,7 @@ _ostree_fetcher_should_retry_request (const GError *error, guint n_retries_remai + * a #GIOErrorEnum. This will return %G_IO_ERROR_FAILED if the status code is + * unknown or otherwise unhandled. */ + GIOErrorEnum +-_ostree_fetcher_http_status_code_to_io_error (guint status_code) ++_ostree_fetcher_http_status_code_to_io_error (guint status_code, gboolean should_retry) + { + switch (status_code) + { +@@ -235,8 +235,9 @@ _ostree_fetcher_http_status_code_to_io_error (guint status_code) + case 408: /* SOUP_STATUS_REQUEST_TIMEOUT */ + return G_IO_ERROR_TIMED_OUT; + case 500: /* SOUP_STATUS_INTERNAL_SERVER_ERROR */ +- return G_IO_ERROR_BUSY; ++ /* retries are always mapped to timeouts, see similar logic in the curl error handling */ ++ return should_retry ? G_IO_ERROR_TIMED_OUT : G_IO_ERROR_BUSY; + default: +- return G_IO_ERROR_FAILED; ++ return should_retry ? G_IO_ERROR_TIMED_OUT : G_IO_ERROR_FAILED; + } + } +diff --git a/src/libostree/ostree-fetcher-util.h b/src/libostree/ostree-fetcher-util.h +index 97233e1f..ef5ad657 100644 +--- a/src/libostree/ostree-fetcher-util.h ++++ b/src/libostree/ostree-fetcher-util.h +@@ -57,7 +57,7 @@ void _ostree_fetcher_journal_failure (const char *remote_name, const char *url, + + gboolean _ostree_fetcher_should_retry_request (const GError *error, guint n_retries_remaining); + +-GIOErrorEnum _ostree_fetcher_http_status_code_to_io_error (guint status_code); ++GIOErrorEnum _ostree_fetcher_http_status_code_to_io_error (guint status_code, gboolean retry_all); + + G_END_DECLS + +-- +2.43.0 + diff --git a/ostree.spec b/ostree.spec index 8040a34..4e3ec82 100644 --- a/ostree.spec +++ b/ostree.spec @@ -13,6 +13,8 @@ Source0: https://github.com/ostreedev/%{name}/releases/download/v%{version}/libo License: LGPL-2.0-or-later URL: https://ostree.readthedocs.io/en/latest/ +Patch0: 0001-curl-Also-map-HTTP-errors-for-retries.patch + # Conditional to ELN right now to reduce blast radius; xref # https://github.com/containers/composefs/pull/229#issuecomment-1838735764 %if 0%{?rhel} >= 10