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)
Ответ на: комментарий от wolverin

Я подозреваю, что ты всё-таки рабораешь с буфферами как-то неправильно.
SPS/PPS после того, как встретились однажды в потоке, регистириуются в декодере по указанному номеру (обычно 0 как и в твоём случае) и сидят в нём пока не перепишутся новым. Твоя ошибка означает что ты передал кадр видео перед IDR. Это в любом случае ошибка. Либо твой SPS/PPS в памяти декодера как-то затёрся (чтр вполне объясняет возмржные bus error'ы, либо ты пересоздал декодер и не передал туда IDR (но сегфолтить оно тогда не должно)
А может такое быть, что ты пересоздал декодер, но где-то ещё работает старый? Попробуй с санитайзерами собрать ffmpeg (можешь его прям забандлить в приложение, они всё равно вечно API ломают)

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

да все либы статично слинкованы

пока сделал так, что если декодер возвращает EAGAIN, то не посылаю ему новые кадры один за другим, а жду следующего буфера с SPS - пока без сегфола (подозреваю что при ошибках единственный кольцевой буфер чтения с камеры успевал изменить память потока декодера)

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

Декодер хранит данные SPS прямо в колтцевом буфере? Этоидовольно странно. Вообще SPS/PPS обычно не меняются, так что можно запомнить последний SPS и продолжать с ним.
Передавать данные без SPS весьма нехорошр, ведь от SPS/PPS зависит то, какие биты packed header'ов декодер ожидает в потоке, а какие нет. Там variable length encoding и заголовок экономит каждый бит. А от неправильных значений тех же, например referenced кадров (что уже считай memory operation плохо написанный декодер наверно и сегфолтнуть может. Но безопасный декодер не должен и видимо там всё же что-то с памятью.
У меня ffmpeg так не сегфолтился, а вот всякие на коленке написанные анализаторы потока - очень даже сыпались даже там, где поток нормально воспрозиводится.

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

нет декодер берет из буфера AVPacket в котором точно есть SPS, если присылает EAGAIN, то раньше просто досылал ему все следующие считанные буферы, сейчас жду когда появится свежий буфер с SPS, а поскольку очередь длиной 2 gop - поток чтения с камеры в кольцо не должен успеть пробежать круг.

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

Ещё одну странгость замечал с ffmpeg с rtp - при потере данных или длитеьной задержке он зачем-то пытается выделить новые буфферы под кадры. При ручной аллокации фреймов это вызывает проблемы. Когда я шарил фреймы между процессами - сначала понадобилось увеличить количество передаваемых кадров до 12, а потом вобще до 24. Иной раз проще перезапустить декодер с нуля, чтобы не делал «мозги»

mittorn ★★★★★
()