I'm not sure if I hit a bug or I'm miss using the RedisModule_Yield function.

I seem to hit:

void whileBlockedCron(void) {
    serverAssert(server.blocked_last_cron);

Here's my crash log:

2025-08-10 21:58:14.549 2025-08-10T18:58:14.121738425Z stdout F === REDIS BUG REPORT START: Cut & paste starting from here ===
2025-08-10 21:58:14.549 2025-08-10T18:58:14.121749583Z stdout F 71:M 10 Aug 2025 18:58:14.121 # === ASSERTION FAILED ===
2025-08-10 21:58:14.549 2025-08-10T18:58:14.12244697Z stdout F 71:M 10 Aug 2025 18:58:14.122 # ==> server.c:1566 'server.blocked_last_cron' is not true
2025-08-10 21:58:14.549 2025-08-10T18:58:14.122847406Z stdout F 
2025-08-10 21:58:14.549 2025-08-10T18:58:14.122865046Z stdout F ------ STACK TRACE ------
2025-08-10 21:58:14.549 2025-08-10T18:58:14.17391056Z stdout F 
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208176138Z stdout F 
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208421142Z stdout F 79 thread-pool-wri
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208436252Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x8612b)[0x7f991799d12b]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208442102Z stdout F /lib/x86_64-linux-gnu/libc.so.6(pthread_mutex_lock+0x112)[0x7f99179a3482]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.20844626Z stdout F redis-server *:6379(RM_ThreadSafeContextLock+0x15)[0x563f9a8eb295]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208450474Z stdout F /var/lib/falkordb/bin/falkordb.so(QueryCtx_LockForCommit+0x88)[0x7f9915111f18]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208454647Z stdout F /var/lib/falkordb/bin/falkordb.so(CommitNewEntities+0x7d)[0x7f99150eb9dd]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208458926Z stdout F /var/lib/falkordb/bin/falkordb.so(+0x24e036)[0x7f99150e1036]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208463002Z stdout F /var/lib/falkordb/bin/falkordb.so(ExecutionPlan_Execute+0x4e)[0x7f99150d664e]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208467158Z stdout F /var/lib/falkordb/bin/falkordb.so(+0x235cb5)[0x7f99150c8cb5]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208492919Z stdout F /var/lib/falkordb/bin/falkordb.so(+0x2dd79f)[0x7f991517079f]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208498365Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x891f5)[0x7f99179a01f5]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208502564Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x10989c)[0x7f9917a2089c]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208506422Z stdout F 
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208510642Z stdout F 81 bio_close_file
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208515014Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x85f16)[0x7f991799cf16]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208519264Z stdout F /lib/x86_64-linux-gnu/libc.so.6(pthread_cond_wait+0x1e8)[0x7f991799f5d8]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208523285Z stdout F redis-server *:6379(bioProcessBackgroundJobs+0x2af)[0x563f9a8b75ef]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208527505Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x891f5)[0x7f99179a01f5]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208531595Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x10989c)[0x7f9917a2089c]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208535923Z stdout F 
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208540035Z stdout F 80 redis-server
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208544171Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x85f16)[0x7f991799cf16]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208548327Z stdout F /lib/x86_64-linux-gnu/libc.so.6(pthread_cond_wait+0x1e8)[0x7f991799f5d8]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208552605Z stdout F /var/lib/falkordb/bin/falkordb.so(+0x270b1c)[0x7f9915103b1c]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208556782Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x891f5)[0x7f99179a01f5]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208562119Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x10989c)[0x7f9917a2089c]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208566005Z stdout F 
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208570054Z stdout F 82 bio_aof
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208574073Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x85f16)[0x7f991799cf16]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208578043Z stdout F /lib/x86_64-linux-gnu/libc.so.6(pthread_cond_wait+0x1e8)[0x7f991799f5d8]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208582077Z stdout F redis-server *:6379(bioProcessBackgroundJobs+0x2af)[0x563f9a8b75ef]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208586119Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x891f5)[0x7f99179a01f5]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208590071Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x10989c)[0x7f9917a2089c]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208593811Z stdout F 
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208597915Z stdout F 204 thread-pool-wri
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208602135Z stdout F /lib/x86_64-linux-gnu/libgomp.so.1(+0x1f64e)[0x7f99178e964e]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208606155Z stdout F /lib/x86_64-linux-gnu/libgomp.so.1(+0x1cd68)[0x7f99178e6d68]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208610076Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x891f5)[0x7f99179a01f5]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208614081Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x10989c)[0x7f9917a2089c]
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208617837Z stdout F 
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208621879Z stdout F 83 bio_lazy_free
2025-08-10 21:58:14.550 2025-08-10T18:58:14.208625919Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x85f16)[0x7f991799cf16]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.208638317Z stdout F /lib/x86_64-linux-gnu/libc.so.6(pthread_cond_wait+0x1e8)[0x7f991799f5d8]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.208642592Z stdout F redis-server *:6379(bioProcessBackgroundJobs+0x2af)[0x563f9a8b75ef]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.208646659Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x891f5)[0x7f99179a01f5]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.208650722Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x10989c)[0x7f9917a2089c]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.208654531Z stdout F 
2025-08-10 21:58:14.551 2025-08-10T18:58:14.208658603Z stdout F 71 redis-server *
2025-08-10 21:58:14.551 2025-08-10T18:58:14.208662567Z stdout F redis-server *:6379(whileBlockedCron+0x1b8)[0x563f9a7eefa8]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.208666617Z stdout F redis-server *:6379(processEventsWhileBlocked+0xd5)[0x563f9a81f9f5]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.2086706Z stdout F redis-server *:6379(RM_Yield+0x11d)[0x563f9a8e275d]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.208674582Z stdout F /var/lib/falkordb/bin/falkordb.so(+0x2730e5)[0x7f99151060e5]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.208678555Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0xd479a)[0x7f99179eb79a]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.208682498Z stdout F /lib/x86_64-linux-gnu/libc.so.6(__libc_fork+0x3a)[0x7f99179eaeba]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.208686508Z stdout F redis-server *:6379(redisFork+0x95)[0x563f9a8053c5]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.208832083Z stdout F redis-server *:6379(rewriteAppendOnlyFileBackground+0x85)[0x563f9a881a95]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.208983122Z stdout F redis-server *:6379(serverCron+0xdd7)[0x563f9a7eedc7]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.209138871Z stdout F redis-server *:6379(+0x87089)[0x563f9a7d9089]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.209262761Z stdout F redis-server *:6379(aeMain+0x1b0)[0x563f9a7e34d0]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.20940807Z stdout F redis-server *:6379(main+0x4a1)[0x563f9a7d8741]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.209512161Z stdout F /lib/x86_64-linux-gnu/libc.so.6(+0x2724a)[0x7f991793e24a]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.209624338Z stdout F /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x85)[0x7f991793e305]
2025-08-10 21:58:14.551 2025-08-10T18:58:14.209779132Z stdout F redis-server *:6379(_start+0x21)[0x563f9a7d8eb1]

And this is how I call the function:

// before fork at parent
static void RG_ForkPrepare() {
...
RedisModuleCtx *ctx = RedisModule_GetThreadSafeContext(NULL);
while((gc = GraphIterator_Next(&it)) != NULL) {
    // acquire read lock, guarantee graph isn't modified by a writer
    Graph *g = gc->g;
    Graph_AcquireReadLock(g);  // release in RG_AfterForkParent

    // synchronize all matrices, make sure they're in a consistent state
    // do not force-flush as this can take awhile

    Graph_GetAdjacencyMatrix(g, false);
    RedisModule_Yield(ctx, REDISMODULE_YIELD_FLAG_CLIENTS,
            "preparing to fork");

    Graph_GetNodeLabelMatrix(g);
    RedisModule_Yield(ctx, REDISMODULE_YIELD_FLAG_CLIENTS,
            "preparing to fork");
    ...

Is it legal to call RedisModule_Yield from pthread_atfork fork prepare call back?

Thanks!

Comment From: sundb

@swilly22 did you forget to call ThreadSafeContextLock() to acquire the GIL?

Comment From: onestardao

It looks like the crash is triggered during RedisModule_Yield inside whileBlockedCron, which is being called from a blocked client context.

From the stack trace, the sequence suggests the module yielded control but the blocked client state was either already freed or in an inconsistent state when whileBlockedCron resumed. This can happen if:

The module frees the blocked client or its private data before all yield/resume cycles are completed.

The yield happens during a period where the server is not expecting blocked client callbacks (e.g., wrong thread or after unblock).

To narrow this down, I’d suggest:

Verifying that all calls to RedisModule_Yield are matched with a valid blocked client state.

Checking whether any cleanup logic runs before the yield finishes.

Trying to reproduce with a minimal module that only blocks, yields, and resumes, to see if it’s reproducible without other logic interfering.

This type of crash is often caused by lifecycle mismatch between yield/resume and the blocked client object.