LINUX.ORG.RU

Как поймать Segmentation fault?

 , ,


0

4

Приветствую.

Начал ловить SIGSEGV в непредсказуемые моменты в многопоточке через несколько часов штатной работы, как обычно запустил приложуху в gdb глянул backtrace после падения, вроде ничего криминального, но увеличил область видимость переменных и сделал копию памяти, теперь тот же bt выдает такое

ПРОЧИЙ-ВЫХОЛОП
[New Thread 0xb58ff410 (LWP 16262)]
[Thread 0xb58ff410 (LWP 16262) exited]
БЛА-БЛА-ВЫХЛОП-ПРИЛОЖУХИ
[New Thread 0xb58ff410 (LWP 16292)]
БЛА-БЛА-ВЫХЛОП-ПРИЛОЖУХИ
[Thread 0xb58ff410 (LWP 16292) exited]
БЛА-БЛА-ВЫХЛОП-ПРИЛОЖУХИ
[New Thread 0xb58ff410 (LWP 16418)]

Thread 14 "Recorder" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb0fff410 (LWP 14943)]
malloc_consolidate (av=av@entry=0xb1000010) at malloc.c:4174
4174    malloc.c: No such file or directory.
(gdb) bt
#0  malloc_consolidate (av=av@entry=0xb1000010) at malloc.c:4174
#1  0xb6abff54 in _int_malloc (av=av@entry=0xb1000010, bytes=bytes@entry=1264) at malloc.c:3457
#2  0xb6ac14a2 in __GI___libc_malloc (bytes=bytes@entry=1264) at malloc.c:2920
#3  0xb6ac1aca in __GI___libc_realloc (oldmem=0x0, bytes=1264) at malloc.c:3001
#4  0x00227164 in av_buffer_realloc (pbuf=pbuf@entry=0xb0ff9eb8, size=size@entry=1264) at libavutil/buffer.c:192
#5  0x0011113a in packet_alloc (size=1200, buf=0xb0ff9eb8) at libavcodec/avpacket.c:88
#6  av_new_packet (pkt=pkt@entry=0x6fb020, size=size@entry=1200) at libavcodec/avpacket.c:100
#7  0x00109736 in ff_h264_handle_frag_packet (nal_header_len=1, nal_header=<synthetic pointer>, start_bit=0, len=1200,
    buf=0x71265e "\212\225杖A\357̰\f\356\243\315\300\066T\353US{7\231^\035\271\214>Q\n\346\232{b<\032\067\070y\203_\277M\004l7\240\301\005\305\332\334\304\006\361\366K\310>\377|\310$\020\233\334\030\363L\212\224)b\207\n_\325_\023\321囖\022\062\034\254X\341\205A\353\035", pkt=0x6fb020) at libavformat/rtpdec_h264.c:273
#8  h264_handle_packet_fu_a (nal_counters=0x0, nal_mask=31, data=<optimized out>, len=1200,
    buf=0x71265e "\212\225杖A\357̰\f\356\243\315\300\066T\353US{7\231^\035\271\214>Q\n\346\232{b<\032\067\070y\203_\277M\004l7\240\301\005\305\332\334\304\006\361\366K\310>\377|\310$\020\233\334\030\363L\212\224)b\207\n_\325_\023\321囖\022\062\034\254X\341\205A\353\035", pkt=0x6fb020, ctx=<optimized out>) at libavformat/rtpdec_h264.c:308
#9  h264_handle_packet (ctx=<optimized out>, data=<optimized out>, st=0x6fea10, pkt=0x6fb020, timestamp=0xb0ff9f48,
    buf=0x71265c "|\001\212\225杖A\357̰\f\356\243\315\300\066T\353US{7\231^\035\271\214>Q\n\346\232{b<\032\067\070y\203_\277M\004l7\240\301\005\305\332\334\304\006\361\366K\310>\377|\310$\020\233\334\030\363L\212\224)b\207\n_\325_\023\321囖\022\062\034\254X\341\205A\353\035", len=1202, seq=4736, flags=0) at libavformat/rtpdec_h264.c:359
#10 0x00107308 in rtp_parse_packet_internal (s=0x6ff020, pkt=0x6fb020,
    buf=0x71265c "|\001\212\225杖A\357̰\f\356\243\315\300\066T\353US{7\231^\035\271\214>Q\n\346\232{b<\032\067\070y\203_\277M\004l7\240\301\005\305\332\334\304\006\361\366K\310>\377|\310$\020\233\334\030\363L\212\224)b\207\n_\325_\023\321囖\022\062\034\254X\341\205A\353\035", len=1202) at libavformat/rtpdec.c:762
#11 0x001080ce in rtp_parse_one_packet (len=1214, bufptr=<optimized out>, pkt=0x6fb020, s=0x6ff020) at libavformat/rtpdec.c:916
#12 ff_rtp_parse_packet (s=0x6ff020, pkt=pkt@entry=0x6fb020, bufptr=bufptr@entry=0x6fd490, len=len@entry=1214)
    at libavformat/rtpdec.c:950
#13 0x000e8f98 in ff_rtsp_fetch_packet (s=s@entry=0x6fabb0, pkt=pkt@entry=0x6fb020) at libavformat/rtsp.c:2276
#14 0x000ead78 in rtsp_read_packet (s=0x6fabb0, pkt=0x6fb020) at libavformat/rtspdec.c:912
#15 0x000b58a4 in ff_read_packet (s=s@entry=0x6fabb0, pkt=pkt@entry=0x6fb020) at libavformat/demux.c:570
#16 0x000b6288 in read_frame_internal (s=0x6fabb0, pkt=0x6fb020) at libavformat/demux.c:1248
#17 0x000b6cf0 in av_read_frame (s=0x6fabb0, pkt=0x6fb020) at libavformat/demux.c:1455
#18 0x000301dc in CHandleH264::HandleRead(CHandlers::stPkt_t&) ()
#19 0x0002e7ea in CHandlers::VideoReaderLoop() ()
#20 0xb6c87dc8 in ?? () from /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
#21 0xb6f2d5b4 in start_thread (arg=0x0) at pthread_create.c:335
#22 0xb6b01c3c in ?? () at ../sysdeps/unix/sysv/linux/arm/clone.S:89 from /lib/arm-linux-gnueabihf/libc.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Вродь ничего в HandleRead эдакого у меня нет с выделением памяти или выходом за границы, обычный кольцевой буфер по модулю

Погуглил про malloc_consolidate, пишут сделать export MALLOC_CHECK_=3 для поиска кривого места в коде и теперь уже скоро сутки не могу уронить приложение как не гоняю, хотя падало вообще даже не под особой нагрузкой, почти в простое, через 2-6 часов…

Осталось еще valgrind попробовать, но раньше использовал его только для поиска места утечки в чужом коде, но визуально за 12 часов процессорного времени течи не наблюдаю (26мб памяти + 140мб виртуальной).

★★★

Последнее исправление: Dimez (всего исправлений: 2)

Добро пожаловать во всратый мир крестов. Если еще не понял.

Это ты еще не отлаживал говно на крестах, которое в релизной сборке падает на клиентской машине, к которой нет доступа. Через корку.

Это одна из причине по которой кресты, да и в принципе сишечку, надо выкидывать отовсюду откуда можно.

Для видеостриминга вообще с головой и за глаза хватает дотнета или же например лиспа.

lovesan ★★★
()

Ошибки с malloc это обычное дело когда повреждается куча из-за багов с переполнением буфера выделенного через malloc. -fsanitize=address должно быть достаточно чтобы поймать падение, и должно быть проще использования valgrind.

jpegqs
()
Ответ на: комментарий от jpegqs

и должно быть проще использования valgrind

Намного быстрее в плане производительности. Но требует перекомпиляции проекта, в отличие от valgrind. Для валгринда есть гуишки, alleyoop например очень лёгок в использовании

annulen ★★★★★
()
Последнее исправление: annulen (всего исправлений: 1)

Настрой чтоб при сегфолте создавало корку. Потом помедитируешь над ней на досуге.

Когда-то у меня был «неуловиный Джо» в коде на сишке, я сделал чтоб по сигналу создавалась корка и процесс продолжал работать. Потом когда возник глюк, отправил сигнал и отловил где проблема.

iron ★★★★★
()
Ответ на: комментарий от iron

Настрой чтоб при сегфолте создавало корку

Он уже в отладчике сегфолт поймал, и видно повреждение памяти, зачем тут корка. Не, ну конечно может повезти и выпадет крэш с более информативный трейсом, но шансы на это невелики

annulen ★★★★★
()

CHandleH264::HandleRead(CHandlers::stPkt_t&) ()

Получаем ссылку на пакет, не спеша с ним работаем. А тем временем тред принимающий пакеты решает что память под нашим пакетом ему нужна…

imatveev13
()
Ответ на: комментарий от raspopov

Можно с ним релизную версию собирать - быстрее ошибка случится.

Не можно, а нужно — не факт, что ошибка вообще воспроизведётся в дебажной версии.

annulen ★★★★★
()

#3 0xb6ac1aca in __GI___libc_realloc (oldmem=0x0, bytes=1264) at malloc.c:3001

Видимо произошла порча памяти кучи. Это могло ароизойти например из-за исподьзования после освобождения, двойного освобождения, записи по неправильному адресу в результате чего повредилась метаинфоомация кучи.

X512 ★★★★★
()
Ответ на: комментарий от anonymous

в моем коде нет прямого вызова realloc, внутри HandleRead работа с очередью, размер которой выделен при запуске и не меняется никогда.

пробую как посоветовали -fsanitize=address -fno-omit-frame-pointer -Wall -pedantic -O3

упало и при export MALLOC_CHECK_=3 не написав ничего

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 3)
Ответ на: комментарий от wolverin

Стек падения почти сразу же уходит в ffmpeg, который часть приложения или нет? Если давать кривые указатели для ffmpeg, который не пересобран с указанными флагами, то он у себя испортит память, санитайзер не поможет.

Например, если ffmpeg нужен буфер большего размера, чем ему передали, и он его переполнит у себя.

jpegqs
()
Ответ на: комментарий от wolverin

Надо пересобрать ffmpeg с санитайзером, если он входит в приложение. В ffmpeg тоже могут быть баги, или он неправильно используется. Кстати, может еще так быть что есть системный libffmpeg и хидеры для него, и есть локальный ffmpeg в приложении, но при сборке хидеры локального путаются с системными. Что может что-нибудь сломать, если есть изменения API между версиями.

jpegqs
()
Ответ на: комментарий от wolverin

Был случай, когда С++ писатель инициализировал поток прямо в конструкторе класса через «initializer list», а поля инициализируются по порядку объявления в классе, этот поток сразу же стартует и начинает обращаться к полям объявленным ниже потока. Есть шанс что эти поля не успеют проинициализироваться, когда поток уже начнёт их использовать. Я этот баг нашел. Типичный С++, когда обмазался абстрациями и уже потерял понимание как это работает.

jpegqs
()
Последнее исправление: jpegqs (всего исправлений: 1)
Ответ на: комментарий от wolverin

Так это же состояние гонки, обычно поток с задержкой выполняется, и класс успевает проинициализироваться. Но если система тормознёт основной поток, и потом запустит дочерний раньше, а это редко происходит, то только тогда будет проблема.

Вот пример по памяти:

#include <chrono>
#include <thread>
#include <iostream>

struct X;
void f1(X *x);

struct W {
  W(int delay) {
    std::this_thread::sleep_for(std::chrono::milliseconds(delay));
  }
};

struct X {
  X() : t(f1, this) {};
  ~X() { t.join(); };
  std::thread t;
  W wait = 10;
  int canary = 123;
};

void f1(X *x) {
  std::cout << x->canary << '\n';
}

int main() { X(); }
jpegqs
()
Ответ на: комментарий от jpegqs

А чего тут искать, санитары это сразу отловят независимо от имеется там задержка или нет, даже если дочерний поток притормозит со стартом и все поля успеют проинициализироваться

anonymous
()
Ответ на: комментарий от AntonI

Меня просто бомбит от таких высказываний. Естественно он тормозит, это интерпретатор машинного кода. Он для того и нужен, чтобы выполнить программу через него и отследить ее поведение.

zx_gamer ★★★
()

А вы уверены, что функции потокобезопасны, которые используются?

Конечно, этот код уже есть, но в следующий раз хорошенько подумайте, а не вариант ли сделать распараллеливание через процессы ОС.

zx_gamer ★★★
()

Слышал про преступление и наказание? Ты в своих прошлых темах очень сильно злоупотреблял хаками в многопоточном программировании. Цпп такое не прощает и награждает сегфолтами. Теперь наслаждайся.

ox55ff ★★★★★
()

если пользуете внешний код в разных потоках, надо обязательно выяснить насколько он thread-safe - это должно быть написано большими красными буквами в любой документации.

если он не thread-safe, можете убиться от стену, но никакого нормального многопотока на таком коде вы не получите.

зарактер повреждений говорит о том, что похоже ваша либа не thread safe. ну или ваш код работы с ней не таков(если она thread-safe).

alysnix ★★★
()
Ответ на: комментарий от wolverin

Да пожалуйста

Требуется реализовать очередную хитро.опую очередь для многопоточной обработки, поступающих с h264 камеры nalu блоков, которые в контексте libav библиотек от ffmpeg будем считать условными кадрами.

На каждую хитроопую очередь у цпп найдётся сегфолт с левой резьбой. И таки нашёлся.

ox55ff ★★★★★
()
Ответ на: комментарий от ox55ff

На каждую хитроопую очередь у цпп найдётся сегфолт с левой резьбой. И таки нашёлся.

пока что звучит как «просто не надо брать C++». А где же «убийство старушки»?

seiken ★★★★★
()
Ответ на: комментарий от ox55ff

) да это ж не первый, прошлый раз помогли найти тоже на форуме этом и сейчас уверен все получится, жду когда упадет

так то да есть мысль такая, ибо уже столкнулся с тем, что нельзя декодированный кадр одновременно 2 потоками пожать в разные кодеки, пришлось копировать память в одном

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 2)
Ответ на: комментарий от ox55ff

На каждую хитроопую очередь у цпп найдётся сегфолт с левой резьбой. И таки нашёлся.

хе хе, а похоже вы без всяких санитайзеров правы, что если всему виной очередь, это объяснило бы длительность до падения (поток чтение с камеры ВДРУГ догоняет поток делающий с нее jpeg) и трассировку стека

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)
Ответ на: комментарий от lovesan

… на крестах, которое в релизной сборке падает на клиентской машине …
… за глаза хватает дотнета …

Как-то раз пришлось воспользоваться либой на Си-шарпе. Всё работало, пока не запустили релизную сборку. Оказалось, как и в Си, там тоже меняют поведение программы в зависимости от типа сборки.

gag ★★★★★
()
Ответ на: комментарий от ox55ff

Эта относится к любому языку. Многопоток это просто тупо сложно. И тупое отсутствие data race вообще не делает программу валидной. И все эти потуги «безопасных» язычков смешны, как и их адепты, которые свято верят, что вот на своём правильном язычке они не наговнокодят как эти старперы на цпп. Примут за обе щеки как только решат написать что-то сложнее простешего примера с одним мьютексом из букваря

anonymous
()
Ответ на: комментарий от nikolnik

Только в языках типа Go у тебя есть инструменты эти ошибки найти и исправить очем быстро, а вот в крестах нет)

Какие там инструменты? Получилось так, что молодые и дерзкие язычки пришли убивать цпп, но великодушный цпп раздал всем своим убийцкам по санитайзеру. Вот Go:

The race detector is based on the C/C++ ThreadSanitizer runtime library, which has been used to detect many errors in Google’s internal code base and in Chromium. The technology was integrated with Go in September 2012; since then it has detected 42 races in the standard library. It is now part of our continuous build process, where it continues to catch race conditions as they arise

Вот и все инструменты. И это только самая элементарщина - отлов data race. Если пишешь не хелоу ворлд с несколькими горутинами, в каждой из которых логика относительно независима, а более менее сложную систему, где несколько потоков, общих данных, мьютексов и тп, то обосраться как два пальца об асфальт на самых простых (вроде бы) задачах - например, поменять состояние всей системы разом, чтобы никто не увидел никакой неконсистентости, при этом, естественно, не вляпаться в dead lock’и, и никакие санитайзеры здесь не помогут. Бьюсь об заклад, львиная доля модников на своих убийцах цпп жидко обделаются и убегут со скулежом обратно писать хелоу ворлды

anonymous
()
Ответ на: комментарий от anonymous

since then it has detected 42 races in the standard library

Статья 2013 года, меньше чем за год в стандартной либе найдено 42 data race )). Охерительные у вас там инструменты, пока цпп не выдал вам санитайзер, даже свою стд не могли написать без говнокода ))

anonymous
()

Интересный конечно спор про языки, только у меня все равно под железо пишется и чем дальше тем более узко, сейчас пришли люто дешёвые ip камеры на goke, натянули на них openipc, картинка огонь, стоят почти ничего, конкуренты так вообще прям на них сервисы мудрят - какие шарпы, го и тыпы )

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)
Ответ на: комментарий от lovesan

Обработку изображений, кодирование и проч. никто дрочить на Питоне не будет. Питон в таких случаях используется как обвязка над сишными или плюсовыми либами.

seiken ★★★★★
()

таки упало с этими санитайзерами с ошибкой Bus error и больше ничего, в gdb не запускал, в дмесге

[129545.817301] Alignment trap: not handling instruction e8502f00 at [<0026aaa8>]
[129545.824701] Unhandled fault: alignment exception (0x221) at 0x45000009
[129545.831377] pgd = db3ba5c0
[129545.834213] [45000009] *pgd=43138003, *pmd=00000000
wolverin ★★★
() автор топика
Ответ на: комментарий от wolverin

Упало уже в ядре? Поздравляю. Видимо ffmpeg использует аппаратное ускорение.

Это может быть не связанной проблемой, а багом в ffmpeg или драйверах. Если вы крутили код несколько суток под полной загрузкой, то это может быть сбой железа вызванный перегревом.

jpegqs
()
Ответ на: комментарий от jpegqs

сейчас переделал один из потоков работающий с очередью, скорее всего проблема в этом, как заметил @ox55ff

скорее всего поток делающий снимок по полученным с ip камеры кадрам натыкается на кадры, которые не может декодировать (иногда декодер пишет что нибудь в духе non-existing PPS 0 referenced или Error splitting the input into NAL units.), а в общем случае я декодеру подсовываю буфер из очереди в котором SPS блок находится и поэтому почти всегда работает, но иногда видимо не успевает и поток чтения с камеры переписывает буфер)

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 2)