exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit 707d9803c6eeaa3542e2459cc2cf47370f007440
parent 5d6b4317d8f87874a098b8e5e1c513e68d7b40f3
Author: Christian Grothoff <grothoff@gnunet.org>
Date:   Mon, 17 Aug 2026 17:00:26 +0200

fix helper cleanup on signal

Diffstat:
Msrc/mhd/mhd_typst.c | 64+++++++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 49 insertions(+), 15 deletions(-)

diff --git a/src/mhd/mhd_typst.c b/src/mhd/mhd_typst.c @@ -362,11 +362,17 @@ pdftk_done_cb (void *cls, case GNUNET_OS_PROCESS_RUNNING: /* we should not get this notification */ GNUNET_break (0); - return; + typst_context_fail (tc, + TALER_EC_EXCHANGE_GENERIC_PDFTK_CRASH, + "pdftk in unexpected state"); + break; case GNUNET_OS_PROCESS_STOPPED: /* Someone is SIGSTOPing our helper!? */ GNUNET_break (0); - return; + typst_context_fail (tc, + TALER_EC_EXCHANGE_GENERIC_PDFTK_CRASH, + "pdftk was stopped"); + break; case GNUNET_OS_PROCESS_EXITED: if (0 != exit_code) { @@ -459,6 +465,33 @@ cancel_async (void *cls) /** + * Fail the typst context @a tc and clean it up asynchronously. + * + * Note that several stages may fail within the same SIGCHLD batch, in + * which case the clean-up task will already have been scheduled by the + * first failure; we must not schedule it a second time (and must not + * clean up synchronously, as we are called from the child-death + * notification). + * + * @param[in,out] tc context to fail + * @param ec error code to return to the client + * @param hint hint text to return to the client + */ +static void +stage_fail (struct TALER_MHD_TypstContext *tc, + enum TALER_ErrorCode ec, + const char *hint) +{ + typst_context_fail (tc, + ec, + hint); + if (NULL == tc->t) + tc->t = GNUNET_SCHEDULER_add_now (&cancel_async, + tc); +} + + +/** * Called when a typst helper exited. * * @param cls our `struct TypstStage *` @@ -484,10 +517,16 @@ typst_done_cb (void *cls, case GNUNET_OS_PROCESS_RUNNING: /* we should not get this notification */ GNUNET_break (0); + stage_fail (tc, + TALER_EC_EXCHANGE_GENERIC_TYPST_CRASH, + "Typst in unexpected state"); return; case GNUNET_OS_PROCESS_STOPPED: /* Someone is SIGSTOPing our helper!? */ GNUNET_break (0); + stage_fail (tc, + TALER_EC_EXCHANGE_GENERIC_TYPST_CRASH, + "Typst was stopped"); return; case GNUNET_OS_PROCESS_EXITED: if (0 != exit_code) @@ -501,12 +540,9 @@ typst_done_cb (void *cls, sizeof (err), "Typst exited with status %d", (int) exit_code); - typst_context_fail (tc, - TALER_EC_EXCHANGE_GENERIC_TYPST_TEMPLATE_FAILURE, - err); - GNUNET_assert (NULL == tc->t); - tc->t = GNUNET_SCHEDULER_add_now (&cancel_async, - tc); + stage_fail (tc, + TALER_EC_EXCHANGE_GENERIC_TYPST_TEMPLATE_FAILURE, + err); return; } break; @@ -521,12 +557,9 @@ typst_done_cb (void *cls, sizeof (err), "Typst died with signal %d", (int) exit_code); - typst_context_fail (tc, - TALER_EC_EXCHANGE_GENERIC_TYPST_CRASH, - err); - GNUNET_assert (NULL == tc->t); - tc->t = GNUNET_SCHEDULER_add_now (&cancel_async, - tc); + stage_fail (tc, + TALER_EC_EXCHANGE_GENERIC_TYPST_CRASH, + err); return; } break; @@ -539,7 +572,8 @@ typst_done_cb (void *cls, } if (0 != tc->active_stages) return; - GNUNET_assert (NULL == tc->t); + if (NULL != tc->t) + return; /* clean-up of a failed stage is already scheduled */ tc->t = GNUNET_SCHEDULER_add_now (&complete_response, tc); }