concurrency requires strtok_r

This commit is contained in:
Christian Grothoff 2020-03-19 19:17:56 +01:00
parent 15489275ba
commit 749d9615d1
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
4 changed files with 51 additions and 29 deletions

View File

@ -352,21 +352,22 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,
{ {
unsigned int i; unsigned int i;
const char *fin; 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, memcpy (d,
url, url,
ulen); ulen);
i = 0; i = 0;
args[i++] = strtok (d, "/"); args[i++] = strtok_r (d, "/", &sp);
while ( (NULL != args[i - 1]) && while ( (NULL != args[i - 1]) &&
(i < rh->nargs) ) (i < rh->nargs) )
args[i++] = strtok (NULL, "/"); args[i++] = strtok_r (NULL, "/", &sp);
/* make sure above loop ran nicely until completion, and also /* make sure above loop ran nicely until completion, and also
that there is no excess data in 'd' afterwards */ that there is no excess data in 'd' afterwards */
if ( (i != rh->nargs) || if ( (i != rh->nargs) ||
(NULL == args[i - 1]) || (NULL == args[i - 1]) ||
(NULL != (fin = strtok (NULL, "/"))) ) (NULL != (fin = strtok_r (NULL, "/", &sp))) )
{ {
char emsg[128 + 512]; char emsg[128 + 512];

View File

@ -350,11 +350,13 @@ handle_link_finished (void *cls,
{ {
struct TALER_EXCHANGE_LinkHandle *lh = cls; struct TALER_EXCHANGE_LinkHandle *lh = cls;
const json_t *j = response; const json_t *j = response;
enum TALER_ErrorCode ec;
lh->job = NULL; lh->job = NULL;
switch (response_code) switch (response_code)
{ {
case 0: case 0:
ec = TALER_EC_INVALID_RESPONSE;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
if (GNUNET_OK != if (GNUNET_OK !=
@ -366,14 +368,17 @@ handle_link_finished (void *cls,
} }
break; break;
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
ec = TALER_JSON_get_error_code (j);
/* This should never happen, either us or the exchange is buggy /* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
break; break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
ec = TALER_JSON_get_error_code (j);
/* Nothing really to verify, exchange says this coin was not melted; we /* Nothing really to verify, exchange says this coin was not melted; we
should pass the JSON reply to the application */ should pass the JSON reply to the application */
break; break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
ec = TALER_JSON_get_error_code (j);
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
break; break;
@ -384,12 +389,13 @@ handle_link_finished (void *cls,
(unsigned int) response_code); (unsigned int) response_code);
GNUNET_break (0); GNUNET_break (0);
response_code = 0; response_code = 0;
ec = TALER_JSON_get_error_code (j);
break; break;
} }
if (NULL != lh->link_cb) if (NULL != lh->link_cb)
lh->link_cb (lh->link_cb_cls, lh->link_cb (lh->link_cb_cls,
response_code, response_code,
TALER_JSON_get_error_code (j), ec,
0, 0,
NULL, NULL,
NULL, NULL,

View File

@ -28,6 +28,10 @@
#include "taler_signatures.h" #include "taler_signatures.h"
#include "backoff.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 * Information about a fresh coin generated by the refresh
@ -149,9 +153,9 @@ struct RefreshMeltState
unsigned int double_melt; 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. * Set by the melt callback as it comes from the exchange.
@ -210,9 +214,9 @@ struct RefreshRevealState
unsigned int expected_response_code; 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; 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; rrs->rrh = NULL;
if (rrs->expected_response_code != http_status) 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) || if ( (0 == http_status) ||
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
@ -548,8 +553,9 @@ link_cb (void *cls,
rls->rlh = NULL; rls->rlh = NULL;
if (rls->expected_response_code != http_status) 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) || if ( (0 == http_status) ||
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
@ -830,8 +836,9 @@ melt_cb (void *cls,
rms->rmh = NULL; rms->rmh = NULL;
if (rms->expected_response_code != http_status) 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) || if ( (0 == http_status) ||
(TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
(MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) (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); GNUNET_assert (&melt_run == cmd.run);
rms = cmd.cls; rms = cmd.cls;
rms->do_retry = GNUNET_YES; rms->do_retry = NUM_RETRIES;
return cmd; 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); GNUNET_assert (&refresh_reveal_run == cmd.run);
rrs = cmd.cls; rrs = cmd.cls;
rrs->do_retry = GNUNET_YES; rrs->do_retry = NUM_RETRIES;
return cmd; 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); GNUNET_assert (&refresh_link_run == cmd.run);
rls = cmd.cls; rls = cmd.cls;
rls->do_retry = GNUNET_YES; rls->do_retry = NUM_RETRIES;
return cmd; return cmd;
} }

View File

@ -368,6 +368,11 @@ struct SignInfo
* calling #TALER_TESTING_sign_keys_for_exchange. * calling #TALER_TESTING_sign_keys_for_exchange.
*/ */
const char *auditor_sign_input_filename; 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; ret = GNUNET_SYSERR;
goto fail; goto fail;
} }
if (GNUNET_OK != if ( (GNUNET_OK !=
TALER_TESTING_run_auditor_exchange (si->config_filename, TALER_TESTING_run_auditor_exchange (si->config_filename,
exchange_master_pub, exchange_master_pub,
si->ec->exchange_url, si->ec->exchange_url,
GNUNET_NO)) GNUNET_NO)) &&
(GNUNET_YES == si->db_reset) )
{ {
GNUNET_free (signed_keys_out); GNUNET_free (signed_keys_out);
ret = GNUNET_NO; ret = GNUNET_NO;
goto fail; goto fail;
} }
if (GNUNET_OK != if ( (GNUNET_OK !=
TALER_TESTING_run_auditor_sign (si->config_filename, TALER_TESTING_run_auditor_sign (si->config_filename,
exchange_master_pub, exchange_master_pub,
si->ec->auditor_url, si->ec->auditor_url,
si->auditor_sign_input_filename, si->auditor_sign_input_filename,
signed_keys_out)) signed_keys_out)) &&
(GNUNET_YES == si->db_reset) )
{ {
GNUNET_free (signed_keys_out); GNUNET_free (signed_keys_out);
GNUNET_free (exchange_master_pub); GNUNET_free (exchange_master_pub);
@ -503,7 +510,8 @@ TALER_TESTING_prepare_exchange (const char *config_filename,
struct SignInfo si = { struct SignInfo si = {
.config_filename = config_filename, .config_filename = config_filename,
.ec = ec, .ec = ec,
.auditor_sign_input_filename = "auditor.in" .auditor_sign_input_filename = "auditor.in",
.db_reset = reset_db
}; };
if (GNUNET_OK != if (GNUNET_OK !=