[PATCH 4/4] kdf: handle errors from thread dispatch/wait functions
Jussi Kivilinna
jussi.kivilinna at iki.fi
Fri Jan 28 20:06:16 CET 2022
* 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 at iki.fi>
---
cipher/kdf.c | 15 ++++++++++++---
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
@@ -1270,25 +1270,38 @@ job_thread (void *p)
pthread_exit (NULL);
}
+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 */
--
2.32.0
More information about the Gcrypt-devel
mailing list