From 749d9615d12127a33445ceae21a8fa388d2f64a1 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 19 Mar 2020 19:17:56 +0100 Subject: [PATCH] concurrency requires strtok_r --- src/exchange/taler-exchange-httpd.c | 9 +++--- src/lib/exchange_api_link.c | 8 +++++- src/testing/testing_api_cmd_refresh.c | 31 +++++++++++++-------- src/testing/testing_api_helpers_exchange.c | 32 ++++++++++++++-------- 4 files changed, 51 insertions(+), 29 deletions(-) diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index 0754163bf..feb599bd0 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -352,21 +352,22 @@ proceed_with_handler (const struct TEH_RequestHandler *rh, { unsigned int i; const char *fin; + char *sp; - /* make a copy of 'url' because 'strtok()' will modify */ + /* make a copy of 'url' because 'strtok_r()' will modify */ memcpy (d, url, ulen); i = 0; - args[i++] = strtok (d, "/"); + args[i++] = strtok_r (d, "/", &sp); while ( (NULL != args[i - 1]) && (i < rh->nargs) ) - args[i++] = strtok (NULL, "/"); + args[i++] = strtok_r (NULL, "/", &sp); /* make sure above loop ran nicely until completion, and also that there is no excess data in 'd' afterwards */ if ( (i != rh->nargs) || (NULL == args[i - 1]) || - (NULL != (fin = strtok (NULL, "/"))) ) + (NULL != (fin = strtok_r (NULL, "/", &sp))) ) { char emsg[128 + 512]; diff --git a/src/lib/exchange_api_link.c b/src/lib/exchange_api_link.c index aa508ecf3..756340494 100644 --- a/src/lib/exchange_api_link.c +++ b/src/lib/exchange_api_link.c @@ -350,11 +350,13 @@ handle_link_finished (void *cls, { struct TALER_EXCHANGE_LinkHandle *lh = cls; const json_t *j = response; + enum TALER_ErrorCode ec; lh->job = NULL; switch (response_code) { case 0: + ec = TALER_EC_INVALID_RESPONSE; break; case MHD_HTTP_OK: if (GNUNET_OK != @@ -366,14 +368,17 @@ handle_link_finished (void *cls, } break; case MHD_HTTP_BAD_REQUEST: + ec = TALER_JSON_get_error_code (j); /* This should never happen, either us or the exchange is buggy (or API version conflict); just pass JSON reply to the application */ break; case MHD_HTTP_NOT_FOUND: + ec = TALER_JSON_get_error_code (j); /* Nothing really to verify, exchange says this coin was not melted; we should pass the JSON reply to the application */ break; case MHD_HTTP_INTERNAL_SERVER_ERROR: + ec = TALER_JSON_get_error_code (j); /* Server had an internal issue; we should retry, but this API leaves this to the application */ break; @@ -384,12 +389,13 @@ handle_link_finished (void *cls, (unsigned int) response_code); GNUNET_break (0); response_code = 0; + ec = TALER_JSON_get_error_code (j); break; } if (NULL != lh->link_cb) lh->link_cb (lh->link_cb_cls, response_code, - TALER_JSON_get_error_code (j), + ec, 0, NULL, NULL, diff --git a/src/testing/testing_api_cmd_refresh.c b/src/testing/testing_api_cmd_refresh.c index dd861fae1..2f91df377 100644 --- a/src/testing/testing_api_cmd_refresh.c +++ b/src/testing/testing_api_cmd_refresh.c @@ -28,6 +28,10 @@ #include "taler_signatures.h" #include "backoff.h" +/** + * How often do we retry before giving up? + */ +#define NUM_RETRIES 5 /** * Information about a fresh coin generated by the refresh @@ -149,9 +153,9 @@ struct RefreshMeltState unsigned int double_melt; /** - * Should we retry on (transient) failures? + * How often should we retry on (transient) failures? */ - int do_retry; + unsigned int do_retry; /** * Set by the melt callback as it comes from the exchange. @@ -210,9 +214,9 @@ struct RefreshRevealState unsigned int expected_response_code; /** - * Should we retry on (transient) failures? + * How often should we retry on (transient) failures? */ - int do_retry; + unsigned int do_retry; }; @@ -253,9 +257,9 @@ struct RefreshLinkState unsigned int expected_response_code; /** - * Should we retry on (transient) failures? + * How often should we retry on (transient) failures? */ - int do_retry; + unsigned int do_retry; }; @@ -322,8 +326,9 @@ reveal_cb (void *cls, rrs->rrh = NULL; if (rrs->expected_response_code != http_status) { - if (GNUNET_YES == rrs->do_retry) + if (0 != rrs->do_retry) { + rrs->do_retry--; if ( (0 == http_status) || (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) @@ -548,8 +553,9 @@ link_cb (void *cls, rls->rlh = NULL; if (rls->expected_response_code != http_status) { - if (GNUNET_YES == rls->do_retry) + if (0 != rls->do_retry) { + rls->do_retry--; if ( (0 == http_status) || (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) @@ -830,8 +836,9 @@ melt_cb (void *cls, rms->rmh = NULL; if (rms->expected_response_code != http_status) { - if (GNUNET_YES == rms->do_retry) + if (0 != rms->do_retry) { + rms->do_retry--; if ( (0 == http_status) || (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) @@ -1246,7 +1253,7 @@ TALER_TESTING_cmd_melt_with_retry (struct TALER_TESTING_Command cmd) GNUNET_assert (&melt_run == cmd.run); rms = cmd.cls; - rms->do_retry = GNUNET_YES; + rms->do_retry = NUM_RETRIES; return cmd; } @@ -1356,7 +1363,7 @@ TALER_TESTING_cmd_refresh_reveal_with_retry (struct TALER_TESTING_Command cmd) GNUNET_assert (&refresh_reveal_run == cmd.run); rrs = cmd.cls; - rrs->do_retry = GNUNET_YES; + rrs->do_retry = NUM_RETRIES; return cmd; } @@ -1405,6 +1412,6 @@ TALER_TESTING_cmd_refresh_link_with_retry (struct TALER_TESTING_Command cmd) GNUNET_assert (&refresh_link_run == cmd.run); rls = cmd.cls; - rls->do_retry = GNUNET_YES; + rls->do_retry = NUM_RETRIES; return cmd; } diff --git a/src/testing/testing_api_helpers_exchange.c b/src/testing/testing_api_helpers_exchange.c index bed6bc8d5..56f8bd548 100644 --- a/src/testing/testing_api_helpers_exchange.c +++ b/src/testing/testing_api_helpers_exchange.c @@ -368,6 +368,11 @@ struct SignInfo * calling #TALER_TESTING_sign_keys_for_exchange. */ const char *auditor_sign_input_filename; + + /** + * Did we reset the database? + */ + int db_reset; }; @@ -448,23 +453,25 @@ sign_keys_for_exchange (void *cls, ret = GNUNET_SYSERR; goto fail; } - if (GNUNET_OK != - TALER_TESTING_run_auditor_exchange (si->config_filename, - exchange_master_pub, - si->ec->exchange_url, - GNUNET_NO)) + if ( (GNUNET_OK != + TALER_TESTING_run_auditor_exchange (si->config_filename, + exchange_master_pub, + si->ec->exchange_url, + GNUNET_NO)) && + (GNUNET_YES == si->db_reset) ) { GNUNET_free (signed_keys_out); ret = GNUNET_NO; goto fail; } - if (GNUNET_OK != - TALER_TESTING_run_auditor_sign (si->config_filename, - exchange_master_pub, - si->ec->auditor_url, - si->auditor_sign_input_filename, - signed_keys_out)) + if ( (GNUNET_OK != + TALER_TESTING_run_auditor_sign (si->config_filename, + exchange_master_pub, + si->ec->auditor_url, + si->auditor_sign_input_filename, + signed_keys_out)) && + (GNUNET_YES == si->db_reset) ) { GNUNET_free (signed_keys_out); GNUNET_free (exchange_master_pub); @@ -503,7 +510,8 @@ TALER_TESTING_prepare_exchange (const char *config_filename, struct SignInfo si = { .config_filename = config_filename, .ec = ec, - .auditor_sign_input_filename = "auditor.in" + .auditor_sign_input_filename = "auditor.in", + .db_reset = reset_db }; if (GNUNET_OK !=