Skip to content

Preload doesn't prevent crashing on module load for older versions #200

@zackcam

Description

@zackcam

We were looking at using preload in Bloom, by moving the following code from init to preload.

    let ver = ctx
        .get_server_version()
        .expect("Unable to get server version!");
    if !valid_server_version(ver) {
        ctx.log_warning(
            format!(
                "The minimum supported Valkey server version for the valkey-bloom module is {:?}",
                configs::BLOOM_MIN_SUPPORTED_VERSION
            )
            .as_str(),
        );
        Status::Err
    } else {
        Status::Ok
    }

From my understanding this should run before trying to load the module and reject it without crashing if the server is not on a supported version.

When testing this for a valkey server with version 7.2 I would see this in the logs followed by a crash

=== REDIS BUG REPORT START: Cut & paste starting from here ===
33463:M 29 Apr 2025 21:02:09.227 # valkey 7.2.5 crashed by signal: 11, si_code: 1
33463:M 29 Apr 2025 21:02:09.227 # Accessing address: (nil)

From then getting the stack trace we see:

(gdb) c
Continuing.

Thread 1 "valkey-server" received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
Missing separate debuginfos, use: debuginfo-install libgcc-7.3.1-17.amzn2.x86_64
(gdb) bt
#0  0x0000000000000000 in ?? ()
#1  0x00007f1fdff21b44 in RedisModule_Init (ctx=0x7ffd6bf4a9c0, 
    name=0x7ffd6bf493f8 "bf", ver=999999, apiver=1)
    at src/include/redismodule.h:1683
#2  0x00007f1fdff21b77 in Export_RedisModule_Init (
    ctx=0x7ffd6bf4a9c0, name=0x7ffd6bf493f8 "bf", ver=999999, 
    apiver=1) at src/redismodule.c:8
#3  0x00007f1fdfec1f9d in valkey_bloom::RedisModule_OnLoad (
    ctx=0x7ffd6bf4a9c0, argv=0x0, argc=0)
    at /workplace/zackcam/valkeymodule-rs/src/macros.rs:286
#4  0x00000000004e53b6 in moduleLoad (
    path=0x7f1fea42a193 "/home/zackcam/workplace/valkey-bloom/target/release/libvalkey_bloom.so", module_argv=0x0, module_argc=0, 
    is_loadex=is_loadex@entry=0) at module.c:12176
#5  0x00000000004e566e in moduleCommand (c=0x7f1fea528700)
    at module.c:13022
#6  0x00000000004fba82 in call (c=c@entry=0x7f1fea528700, 
    flags=flags@entry=3) at server.c:3519
#7  0x00000000004fc804 in processCommand (c=0x7f1fea528700)
    at server.c:4160
#8  0x0000000000496b57 in processCommandAndResetClient (
    c=0x7f1fea528700) at networking.c:2466
#9  processInputBuffer (c=c@entry=0x7f1fea528700)
    at networking.c:2574
#10 0x000000000049708b in readQueryFromClient (
    conn=<optimized out>) at networking.c:2713
#11 0x000000000054b6a4 in callHandler (handler=<optimized out>, 
    conn=0x7f1fea429580) at connhelpers.h:79
#12 connSocketEventHandler.lto_priv.355 (el=<optimized out>, 
    fd=<optimized out>, clientData=0x7f1fea429580, 
    mask=<optimized out>) at socket.c:298
#13 0x0000000000458c7e in aeProcessEvents (
    eventLoop=eventLoop@entry=0x7f1fea42a140, 
---Type <return> to continue, or q <return> to quit---
    flags=flags@entry=27) at ae.c:436
#14 0x0000000000458fd8 in aeMain (eventLoop=0x7f1fea42a140)
    at ae.c:496
#15 0x000000000044fd81 in main (argc=<optimized out>, 
    argv=<optimized out>) at server.c:7373

This appears to crash on RedisModule_Init before we reach the preload, is this use case invalid for preload or is there an edge case where preload doesn't catch this?
I compared the stack traces for when using init and preload and they were the same as well

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions