From cd946c454113b3441442051204ef9ba68f4213d4 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Mon, 28 Sep 2026 17:35:18 -0500 Subject: [PATCH] Apply fix for threaded channels "eating" values. Reported by @pepe with help from Claude. --- src/core/corelib.c | 6 +++--- src/core/ev.c | 5 ++++- test/suite-ev2.janet | 13 +++++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/core/corelib.c b/src/core/corelib.c index cdaba373..556420ce 100644 --- a/src/core/corelib.c +++ b/src/core/corelib.c @@ -550,9 +550,9 @@ JANET_CORE_FN(janet_core_gensym, JANET_CORE_FN(janet_core_gccollect, "(gccollect)", - "Run garbage collection. You should probably not call this manually.") { + "Run the garbage collector to free unreachable values.") { (void) argv; - (void) argc; + janet_fixarity(argc, 0); janet_collect(); return janet_wrap_nil(); } @@ -561,7 +561,7 @@ JANET_CORE_FN(janet_core_gcsetinterval, "(gcsetinterval interval)", "Set an integer number of bytes to allocate before running garbage collection. " "Low values for interval will be slower but use less memory. " - "High values will be faster but use more memory.") { + "High values will be faster but use more memory. Set to 0 to disable automatic collection.") { janet_fixarity(argc, 1); size_t s = janet_getsize(argv, 0); /* limit interval to 48 bits */ diff --git a/src/core/ev.c b/src/core/ev.c index bd87460b..01077def 100644 --- a/src/core/ev.c +++ b/src/core/ev.c @@ -977,7 +977,10 @@ static void janet_thread_chan_cb(JanetEVGenericMessage msg) { break; } if (!sent) { - janet_chan_unpack(channel, &x, 1); + if (channel->closed || janet_q_push_head(&channel->items, &x, sizeof(Janet))) { + /* channel is closed or full. Otherwise, keep it. */ + janet_chan_unpack(channel, &x, 1); + } } } else { JanetChannelPending writer; diff --git a/test/suite-ev2.janet b/test/suite-ev2.janet index 24a2e0c8..99020f24 100644 --- a/test/suite-ev2.janet +++ b/test/suite-ev2.janet @@ -101,4 +101,17 @@ (assert (deep= @"hello\nworld2\n" (slurp "tmp/out.txt")) "file threading 1") (assert (deep= @"world1\nabc\n" (slurp "tmp/out2.txt")) "file threading 2") +# A value given to a threaded channel whose only waiting reader has since been +# resumed by another select clause must be kept for the next reader. +(def stale-tchan (ev/thread-chan 10)) +(def stale-pchan (ev/chan 10)) +(ev/spawn (ev/select stale-tchan stale-pchan)) +(ev/sleep 0) +(ev/give stale-pchan 1) +(ev/sleep 0) +(ev/give stale-tchan 42) +(ev/sleep 0.01) +(assert (= 42 (try (ev/with-deadline 1 (ev/take stale-tchan)) ([_] nil))) + "value given to a threaded channel with a stale reader is kept") + (end-suite)