segfault in g_slice_alloc

2019-08-09 10:39发布

问题:

I am calling a function with the following lines:

void call_system_command(const char *command_params)
{
    GString *cmd = g_string_sized_new(1024);
    g_string_append_printf(cmd, "/bin/bash /path/to/my/script '%s'", command_params);
    system(cmd->str);
    g_string_free(cmd, TRUE);
}

I am getting segfault in the line with g_string_sized_new. Backtrace from gdb shows:

(gdb) bt
#0  0x000000320ce56264 in g_slice_alloc () from /lib64/libglib-2.0.so.0
#1  0x000000320ce5c3db in g_string_sized_new () from /lib64/libglib-2.0.so.0
....

I have tried exporting G_SLICE=always-malloc, so that instead of glib's own allocator, malloc is used. However the problem remains same. I am still getting segfault in g_slice_alloc. Also I am calling this function 'call_system_command' from multiple threads. Could that be a problem?

The function is a part of plugin that is called by cron every 15 minutes. The segfault does not occur every time the plugin is executed but one every 3-4 days.

Any pointers on further debugging will be helpful.

Thanks in advance.

回答1:

You should run your application under Valgrind to help chase this, it sounds like heap corruption.

You mention threads, which of course is good information since it can make it easier to end up in trouble.

The glib documentation states:

GLib itself is internally completely thread-safe (all global data is automatically locked), but individual data structure instances are not automatically locked for performance reasons.

And since the slice API doesn't expose any data structure instances, it should be safe to call from multiple threads.



回答2:

I found the problem. Wrote the following test program to identify the problem.

#include <stdio.h>
#include <glib.h>
#include <pthread.h>

#pragma GCC optimize("O0")

#define NUM 20
void* run(void *d)
{
    int i;
    for (i = 0; i < 1000000; i++) {
        GString *str = g_string_sized_new(1024);
        g_string_append_printf(str, "%s", "hello hello\n");
        fprintf(stdout, "%s", str->str);
        g_string_free(str, TRUE);
    }
    pthread_exit(NULL);
}

int main()
{
    pthread_t threads[NUM];
    int j;
    for (j = 0; j < NUM; j++) {
        pthread_create(&threads[j], NULL, run, (void*) NULL);
    }
    pthread_exit(NULL);

    return 0;
}

The following segfault occurs consistently

Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x7fffecdfa700 (LWP 11277)] 0x000000320ce56257 in g_slice_alloc () from /lib64/libglib-2.0.so.0 Missing separate debuginfos, use: debuginfo-install glib2-2.22.5-6.el6.x86_64 glibc-2.12-1.47.el6.x86_64 libgcc-4.4.6-3.el6.x86_64



回答3:

Where is your pthread_join statement? Your main function actually could finish before your threaded functions return - that could destroy the thread objects themselfes. As far as I know pthread_exit is supposed to be used only within the spawned threads, and not within the mainthread (http://cs.gmu.edu/~white/CS571/Examples/pthread_examples.html, http://man7.org/linux/man-pages/man3/pthread_exit.3.html) So your demo is (possibly) not optimal, and may incorporate the same issue cause as your program.

Did you try to just manually malloc a same sized bunch of memory and check again with valgrind and gdb.