From 3c01f71d9e2b760cbbe567da90684af486731f95 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Wed, 24 Sep 2025 18:52:10 -0400 Subject: [PATCH] itersolve: Don't call trapq_check_sentinels() from itersolve_generate_steps() Commit a89694ac changed the code to run itersolve_generate_steps() from multiple threads simultaneously. However, trapq_check_sentinels() can modify the shared trapq object. So, calling it from multiple threads could introduce a race condition. Move the call to trapq_check_sentinels() to steppersyncmgr_gen_steps() to avoid the issue. Signed-off-by: Kevin O'Connor --- klippy/chelper/itersolve.c | 1 - klippy/chelper/steppersync.c | 12 ++++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/klippy/chelper/itersolve.c b/klippy/chelper/itersolve.c index 9b1206249..5b1683606 100644 --- a/klippy/chelper/itersolve.c +++ b/klippy/chelper/itersolve.c @@ -151,7 +151,6 @@ itersolve_generate_steps(struct stepper_kinematics *sk, struct stepcompress *sc sk->last_flush_time = flush_time; if (!sk->tq) return 0; - trapq_check_sentinels(sk->tq); struct move *m = list_first_entry(&sk->tq->moves, struct move, node); while (last_flush_time >= m->print_time + m->move_t) m = list_next_entry(m, node); diff --git a/klippy/chelper/steppersync.c b/klippy/chelper/steppersync.c index 4dede38fb..6b571f4b6 100644 --- a/klippy/chelper/steppersync.c +++ b/klippy/chelper/steppersync.c @@ -21,6 +21,7 @@ #include "serialqueue.h" // struct queue_message #include "stepcompress.h" // stepcompress_flush #include "steppersync.h" // steppersync_alloc +#include "trapq.h" // trapq_check_sentinels /**************************************************************** @@ -397,6 +398,17 @@ steppersyncmgr_gen_steps(struct steppersyncmgr *ssm, double flush_time , double gen_steps_time, double clear_history_time) { struct steppersync *ss; + // Prepare trapqs for step generation + list_for_each_entry(ss, &ssm->ss_list, ssm_node) { + struct syncemitter *se; + list_for_each_entry(se, &ss->se_list, ss_node) { + if (!se->sc || !se->sk) + continue; + struct trapq *tq = itersolve_get_trapq(se->sk); + if (tq) + trapq_check_sentinels(tq); + } + } // Start step generation threads list_for_each_entry(ss, &ssm->ss_list, ssm_node) { uint64_t flush_clock = clock_from_time(&ss->ce, flush_time);