summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@iki.fi>2022-01-28 20:33:08 +0200
committerJussi Kivilinna <jussi.kivilinna@iki.fi>2022-01-28 21:03:28 +0200
commit54369c66bedd20d6846ed8fab678082ec8eecf5d (patch)
tree95be21561610482bd4ad7592f984a671e23ddd46
parent409f69167983deacee6d6c85c80a4be0e4b5d7c1 (diff)
downloadlibgcrypt-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.c15
-rw-r--r--tests/t-kdf.c24
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 */