segfault в g_slice_alloc
Я вызываю функцию со следующими строками:
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);
}
Я получаю segfault в строке с g_string_sized_new. Backtrace от GDB показывает:
(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
....
Я попытался экспортировать G_SLICE=always-malloc, чтобы вместо собственного распределителя glib использовался malloc. Однако проблема остается той же. Я все еще получаю segfault в g_slice_alloc. Также я вызываю эту функцию 'call_system_command' из нескольких потоков. Может ли это быть проблемой?
Эта функция является частью плагина, который вызывается cron каждые 15 минут. Сегфоут происходит не каждый раз, когда плагин запускается, а один раз в 3-4 дня.
Любые указатели на дальнейшую отладку будут полезны.
Заранее спасибо.
3 ответа
Я нашел проблему. Написал следующую тестовую программу для выявления проблемы.
#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;
}
Следующий segfault происходит последовательно
Программа получила сигнал SIGSEGV, Ошибка сегментации. [Переключение на поток 0x7fffecdfa700 (LWP 11277)] 0x000000320ce56257 в g_slice_alloc () из /lib64/libglib-2.0.so.0 Отсутствует отдельный debuginfos, используйте: debuginfo-install glib2-2.22.5-6.el6.x86_64 glic 1.47.el6.x86_64 libgcc-4.4.6-3.el6.x86_64
Вы должны запустить свое приложение под Valgrind, чтобы помочь в этом, это похоже на повреждение кучи.
Вы упоминаете темы, которые, конечно, являются полезной информацией, поскольку могут облегчить возникновение проблем.
Документация glib гласит:
Сам GLib является внутренне полностью поточно-ориентированным (все глобальные данные автоматически блокируются), но отдельные экземпляры структуры данных не блокируются автоматически по соображениям производительности.
А поскольку API слайса не предоставляет никаких экземпляров структуры данных, его можно безопасно вызывать из нескольких потоков.
Где твое pthread_join
заявление? Ваша основная функция на самом деле может завершиться до того, как вернутся многопоточные функции - это может привести к самому разрушению объектов потока. Насколько я знаю pthread_exit
предполагается использовать только в порожденных потоках, а не в основной цепочке ( http://cs.gmu.edu/~white/CS571/Examples/pthread_examples.html, http://man7.org/linux/man-pages/man3/pthread_exit.3.html) Таким образом, ваша демонстрация (возможно) не является оптимальной и может включать ту же причину проблемы, что и ваша программа.
Вы пытались просто вручную malloc
куча памяти того же размера и проверьте еще раз с помощью valgrind и gdb.