csegmentation-faultopenwrt

Segmentation fault in uBus program


I am using the ubus message service provided by OpenWrt. I have written a simple ubus object in C. The object exposes a single method which does not take any parameters, and returns a response of "Hello and welcome". When I register the object on the ubus and call its method using the command line, it works. But the catch is it works only for the first call or the first two calls. After those two calls, I get Segmentation fault. I tried debugging using gdb but it points to a source file in the libubus library. I highly doubt that there might be something wrong with the library itself.

I have also tried using Valgrind but it doesn't seem to work on my system, and I can't seem to fix that either.

I am attaching the source code, the ubus terminal output, the gdb logs and the Valgrind error logs below. Any and all help is greatly appreciated.

Source code:

#include <stdio.h>
#include <libubus.h>

// Handler function for the ubus method
static int my_ubus_method(struct ubus_context *ctx, struct ubus_object *obj,
                          struct ubus_request_data *req, const char *method,
                          struct blob_attr *msg)
{
    // Handle the incoming ubus message here
    printf("Received method: %s\n", method);

    // Reply with a simple response
    struct blob_buf b;
    blob_buf_init(&b, 0);
    const char *response_str = "Hello and welcome";
    blobmsg_add_string(&b, "response", response_str);
    
    ubus_send_reply(ctx, req, b.head);

    blob_buf_free(&b);

    return UBUS_STATUS_OK;
}

static const struct blobmsg_policy my_method_policy[] = {};

// Define the ubus methods array
static const struct ubus_method my_ubus_methods[] = {
    UBUS_METHOD("my_method", my_ubus_method, my_method_policy),
};

// Define the ubus object type
static struct ubus_object_type my_ubus_obj_type =
    UBUS_OBJECT_TYPE("my_object", my_ubus_methods);

// Define the ubus object
static struct ubus_object my_ubus_obj = {
    .name = "my_object",
    .type = &my_ubus_obj_type,
    .methods = my_ubus_methods,
    .n_methods = ARRAY_SIZE(my_ubus_methods),
};

int main()
{
    uloop_init();

    struct ubus_context *ctx = ubus_connect(NULL);
    if (!ctx) {
        fprintf(stderr, "Failed to connect to ubus\n");
        return -1;
    }

    ubus_add_uloop(ctx);

    int ret = ubus_add_object(ctx, &my_ubus_obj);
    if (ret) {
        fprintf(stderr, "Failed to add ubus object: %s\n", ubus_strerror(ret));
        ubus_free(ctx);
        return -1;
    }

    printf("Server running...\n");

    uloop_run();
    ubus_free(ctx);

    uloop_done();


    return 0;
}

Terminal output from uBus: Terminal output from uBus

gdb logs: gdb logs

Valgrind error logs Valgrind error logs


Solution

  • I couldn't find what causes the problem, but I found a fix for that: just change blob_buf variable to a static variable and code will run:

    static struct blob_buf b;
    

    and the second note that I prefer to use UBUS_METHOD_NOARG when defining ubus methods that won't take any arguments:

    // You wont need blobmsg_policy anymore
    // static const struct blobmsg_policy my_method_policy[] = {};
    
    // Define the ubus methods array
    static const struct ubus_method my_ubus_methods[] = {
        UBUS_METHOD_NOARG("my_method", my_ubus_method),
    };