Tl; dr
Каким-то образом асинхронные обратные вызовы из одной библиотеки обнаруживаются в стеке вызовов из другой библиотеки, даже если они не общаются напрямую друг с другом.Сбой происходит, когда одна библиотека вызывает select
, в то время как другая имеет три потока, вызывающих poll
.
Резюме
У меня есть проект, использующий функции двух сторонних библиотек.Они оба прекрасно работают в изоляции, но когда я помещаю их в одну и ту же программу, в ней возникают ошибки.Дело в том, что они не вызывают друг друга напрямую, но как-то стек показывает, что они есть.Оба полагаются на многопоточность и / или асинхронные обратные вызовы.
Цель
Я пытаюсь считать USB-камеру с закрытым исходным кодом C ++ Basler Pylon API .С помощью этой библиотеки вы - подключаетесь к физической камере, создавая экземпляр объекта InstantCamera
.
- Затем вы можете вызвать InstantCamera::StartGrabbing()
, чтобы запустить новый поток, который непрерывно загружает изображения во внутренний буфер FIFO.
- НаконецВы вызываете InstantCamera::RetrieveResult(int timeout, CGrabResultPtr& grabResult)
, чтобы поместить следующее изображение из очереди в CGrabResultPtr, который является объектом интеллектуального указателя.Этот вызов блокируется в течение timeout
мс, если изображение еще не готово.
Я пытаюсь соединить это с более крупной системой сбора научных данных со многими другими инструментами, связывающимися с открытым исходным кодом C Среда сбора данных MIDAS .Как я уже писал, клиентская программа MIDAS, которая должна считывать изображения с камеры, выполняет: - При запуске создаёт экземпляр нового объекта InstantCamera
и проверяет, что мы можем получить из него одно изображение.- Перейдите в цикл ожидания, который вызывает встроенную функцию MIDAS cm-yield
, которая проверяет, были ли получены какие-либо сообщения, а затем бездействует в течение некоторого времени ожидания вызова RPC.
Проблема
Цикл холостого хода MIDAS является внутренним на 100%, и, тем не менее, если камера когда-либо считывалась, это вызывает сбой.Типичная обратная трассировка выглядит следующим образом:
Program terminated with signal 6, Aborted.
#0 0x00007f6de275a277 in __GI_raise (sig=sig@entry=6)>
at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
(gdb) bt
#0 0x00007f6de275a277 in __GI_raise (sig=sig@entry=6)
at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1 0x00007f6de275b968 in __GI_abort () at abort.c:90
#2 0x00007f6de30697d5 in __gnu_cxx::__verbose_terminate_handler() ()
at ../../../../libstdc++-v3/libsupc++/vterminate.cc:95
#3 0x00007f6de3067746 in __cxxabiv1::__terminate(void (*)()) (handler= <optimized out>) at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:38
#4 0x00007f6de3067773 in std::terminate() ()
at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:48
#5 0x00007f6de3067993 in __cxxabiv1::__cxa_throw(void*, std::type_info*, void (*)(void*)) (obj=0x230e110, tinfo=0x7f6de6da58f0 <typeinfo for GenICam_3_0_Basler_pylon_v5_0::RuntimeException>, dest=0x7f6de6afdd6e <GenICam_3_0_Basler_pylon_v5_0::RuntimeException::~RuntimeException()>)
at ../../../../libstdc++-v3/libsupc++/eh_throw.cc:87
#6 0x00007f6de6b38421 in Pylon::WaitObjectEx::Signal() ()
at /opt/pylon5/lib64/libpylonbase-5.0.12.so
#7 0x00007f6de6fd26d0 in <signal handler called> () at /lib64/libpthread.so.0
#8 0x00007f6de2819c73 in select () at ../sysdeps/unix/syscall-template.S:81
#9 0x0000000000434ebe in ss_suspend (millisec=millisec@entry=100, msg=msg@entry=0) at src/system.c:4075
#10 0x0000000000431855 in cm_yield (millisec=millisec@entry=100)
at src/midas.c:5041
#11 0x0000000000417d77 in scheduler () at src/mfe.c:2564
---Type <return> to continue, or q <return> to quit---
#12 0x000000000040f67c in main (argc=<optimized out>, argv=<optimized out>)
at src/mfe.c:2899
Как вы можете видеть, внутренний холостой цикл MIDAS прерывается функцией Pylon, даже если в этот момент они вообще не взаимодействуют в программе.Обратный след всех нитей показывает основной цикл холостого хода и 3 связанных с пилоном потока, все в функции poll()
.
Я ничего не знаю о poll
и select
, кроме того, что они связаны друг с другом и имеют какое-то отношение к праздной блокировке во время ожидания доступных данных.Они конечно кажутся подозрительными здесь.
Вопрос
Как я могу выяснить, что эти библиотеки делают друг с другом, что вызывает столько проблем?Или, более конкретно, есть ли способ изолировать эти библиотеки / вызовы, чтобы они перестали мешать?
У меня есть доступ к источнику MIDAS (цикл бездействия, вызывающий select
), но не к коду pylon (3 потока, вызывающего poll
).Редактирование источника MIDAS для целей отладки - это хорошо, но я бы хотел избежать его разветвления, если это возможно (если только это не настоящая ошибка, которую следует передавать в апстрим).