diff options
author | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2022-01-28 20:33:08 +0200 |
---|---|---|
committer | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2022-01-28 21:03:28 +0200 |
commit | 54369c66bedd20d6846ed8fab678082ec8eecf5d (patch) | |
tree | 95be21561610482bd4ad7592f984a671e23ddd46 | |
parent | 409f69167983deacee6d6c85c80a4be0e4b5d7c1 (diff) | |
download | libgcrypt-54369c66bedd20d6846ed8fab678082ec8eecf5d.tar.gz |
kdf: handle errors from thread dispatch/wait functions
* cipher/kdf.c (argon2_compute): Handle failed job dispatch/wait.
* tests/t-kdf.c (pthread_jobs_launch_job)
(wait_all_jobs_completion): Handle errors returned from pthread functions.
--
This allows thread helpers to return error code, which causes
KDF processing to stop.
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
-rw-r--r-- | cipher/kdf.c | 15 | ||||
-rw-r--r-- | tests/t-kdf.c | 24 |
2 files changed, 32 insertions, 7 deletions
diff --git a/cipher/kdf.c b/cipher/kdf.c index 74c5b753..79dc6cd8 100644 --- a/cipher/kdf.c +++ b/cipher/kdf.c @@ -706,6 +706,7 @@ argon2_compute (argon2_ctx_t a, const struct gcry_kdf_thread_ops *ops) unsigned int r; unsigned int s; unsigned int l; + int ret; ec = argon2_fill_first_blocks (a); if (ec) @@ -726,14 +727,22 @@ argon2_compute (argon2_ctx_t a, const struct gcry_kdf_thread_ops *ops) thread_data->lane = l; if (ops) - ops->dispatch_job (ops->jobs_context, - argon2_compute_segment, thread_data); + { + ret = ops->dispatch_job (ops->jobs_context, + argon2_compute_segment, thread_data); + if (ret < 0) + return GPG_ERR_CANCELED; + } else argon2_compute_segment (thread_data); } if (ops) - ops->wait_all_jobs (ops->jobs_context); + { + ret = ops->wait_all_jobs (ops->jobs_context); + if (ret < 0) + return GPG_ERR_CANCELED; + } } return 0; diff --git a/tests/t-kdf.c b/tests/t-kdf.c index 8844e111..4c82fed8 100644 --- a/tests/t-kdf.c +++ b/tests/t-kdf.c @@ -1271,24 +1271,37 @@ job_thread (void *p) } static int +wait_all_jobs_completion (void *jobs_context); + +static int pthread_jobs_launch_job (void *jobs_context, gcry_kdf_job_fn_t job, void *job_priv) { struct user_defined_threads_ctx *ctx = jobs_context; + int ret; if (ctx->next_thread_idx == ctx->oldest_thread_idx) { assert (ctx->num_threads_running == MAX_THREADS); /* thread limit reached, join a thread */ - pthread_join (ctx->thread[ctx->oldest_thread_idx], NULL); + ret = pthread_join (ctx->thread[ctx->oldest_thread_idx], NULL); + if (ret) + return -1; ctx->oldest_thread_idx = (ctx->oldest_thread_idx + 1) % MAX_THREADS; ctx->num_threads_running--; } ctx->work[ctx->next_thread_idx].job = job; ctx->work[ctx->next_thread_idx].priv = job_priv; - pthread_create (&ctx->thread[ctx->next_thread_idx], &ctx->attr, - job_thread, &ctx->work[ctx->next_thread_idx]); + ret = pthread_create (&ctx->thread[ctx->next_thread_idx], &ctx->attr, + job_thread, &ctx->work[ctx->next_thread_idx]); + if (ret) + { + /* could not create new thread. */ + (void)wait_all_jobs_completion (jobs_context); + return -1; + } + if (ctx->oldest_thread_idx < 0) ctx->oldest_thread_idx = ctx->next_thread_idx; ctx->next_thread_idx = (ctx->next_thread_idx + 1) % MAX_THREADS; @@ -1301,11 +1314,14 @@ wait_all_jobs_completion (void *jobs_context) { struct user_defined_threads_ctx *ctx = jobs_context; int i, idx; + int ret; for (i = 0; i < ctx->num_threads_running; i++) { idx = (ctx->oldest_thread_idx + i) % MAX_THREADS; - pthread_join (ctx->thread[idx], NULL); + ret = pthread_join (ctx->thread[idx], NULL); + if (ret) + return -1; } /* reset context for next round of parallel work */ |