2010-08-05 9 views
7

Ho un problema con un'applicazione C++ che ho sviluppato che utilizza dlopen per caricare librerie sviluppate dall'utente. L'applicazione è stata usata da una varietà di persone su una varietà di distribuzioni Linux e versioni di OSX negli ultimi due anni e quindi presumo che il mio uso di dlopen sia OK, così come il codice che dipende da esso (sì, questa è hybris, quindi ti riporto quando fallisce). Il problema che ho ora è che un utente ha sviluppato una libreria che non viene caricata sul mio sistema (OSX 10.6.4). Quando il sistema tenta di caricarlo, si verifica un blocco e un arresto anomalo. Il filo che si blocca assomiglia a questo nella relazione crash:Debug di un arresto anomalo quando una libreria viene aperta tramite dlopen su OSX

Thread 5 Crashed: 
0 com.apple.CoreFoundation  0x00007fff80fa6110 __CFInitialize + 1808 
1 dyld       0x00007fff5fc0d5ce ImageLoaderMachO::doImageInit(ImageLoader::LinkContext const&) + 138 
2 dyld       0x00007fff5fc0d607 ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) + 27 
3 dyld       0x00007fff5fc0bcec ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) + 236 
4 dyld       0x00007fff5fc0bc9d ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) + 157 
5 dyld       0x00007fff5fc0bc9d ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) + 157 
6 dyld       0x00007fff5fc0bc9d ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) + 157 
7 dyld       0x00007fff5fc0bc9d ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) + 157 
8 dyld       0x00007fff5fc0bc9d ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) + 157 
9 dyld       0x00007fff5fc0bda6 ImageLoader::runInitializers(ImageLoader::LinkContext const&) + 58 
10 dyld       0x00007fff5fc08fbb dlopen + 573 
11 libSystem.B.dylib    0x00007fff816492c0 dlopen + 61 
12 cast-server-c++     0x0000000100007819 cast::loadLibrary(std::string const&) + 96 (ComponentCreator.cpp:43) 
13 cast-server-c++     0x00000001000079c7 cast::createComponentCreator(std::string const&) + 24 (ComponentCreator.cpp:87) 
14 cast-server-c++     0x00000001000089c5 cast::CASTComponentFactory::createBase(std::string const&, std::string const&, Ice::Current const&) + 197 (CASTComponentFactory.cpp:27) 
15 cast-server-c++     0x00000001000090e9 cast::CASTComponentFactory::newManagedComponent(std::string const&, std::string const&, bool, Ice::Current const&) + 73 (CASTComponentFactory.cpp:62) 
16 libCDL.dylib     0x00000001009ceb6c cast::interfaces::ComponentFactory::___newManagedComponent(IceInternal::Incoming&, Ice::Current const&) + 218 (CDL.cpp:14904) 
17 libCDL.dylib     0x00000001009cf1d0 cast::interfaces::ComponentFactory::__dispatch(IceInternal::Incoming&, Ice::Current const&) + 572 (CDL.cpp:15057) 
18 libIce.3.3.1.dylib    0x00000001000c9078 IceInternal::Incoming::invoke(IceInternal::Handle<IceInternal::ServantManager> const&) + 2004 (Incoming.cpp:484) 
19 libIce.3.3.1.dylib    0x0000000100091a5d Ice::ConnectionI::invokeAll(IceInternal::BasicStream&, int, int, unsigned char, IceInternal::Handle<IceInternal::ServantManager> const&, IceInternal::Handle<Ice::ObjectAdapter> const&) + 367 (ConnectionI.cpp:2436) 
20 libIce.3.3.1.dylib    0x000000010009bb40 Ice::ConnectionI::message(IceInternal::BasicStream&, IceInternal::Handle<IceInternal::ThreadPool> const&) + 416 (ConnectionI.cpp:1105) 
21 libIce.3.3.1.dylib    0x00000001001a9bbc IceInternal::ThreadPool::run() + 3470 (ThreadPool.cpp:523) 
22 libIce.3.3.1.dylib    0x00000001001aa4ec IceInternal::ThreadPool::EventHandlerThread::run() + 152 (ThreadPool.cpp:782) 
23 libIceUtil.3.3.1.dylib   0x00000001006eb1e9 startHook + 128 (Thread.cpp:375) 
24 libSystem.B.dylib    0x00007fff8167c456 _pthread_start + 331 
25 libSystem.B.dylib    0x00007fff8167c309 thread_start + 13 

(posso inviare il registro completo, se necessario, ma supera il limite di testo corpo se includo nel mio post)

Nel terminale in cui sto eseguendo l'eseguibile l'arresto non produce output tranne per la notifica che lo script che esegue l'eseguibile ha intrappolato un segnale.

La mia domanda è come ottenere ulteriori informazioni su ciò che potrebbe causare questo arresto anomalo? Sono anche felice se qualcuno può suggerire possibili soluzioni, ma per iniziare vorrei almeno sapere come generare più informazioni quando il sistema si arresta in modo anomalo su cosa è effettivamente sbagliato.

Se eseguo otool sulla libreria che viene inizialmente aperta da dlopen, tutto sembra a posto (nessun collegamento mancante, simboli, ecc.). Il mio principale sospetto è che sia la particolare combinazione di librerie che la libreria che viene caricata è collegata a quella che sta causando questo crash in qualche modo. Queste altre librerie possono essere caricate che usano sottoinsiemi diversi di queste librerie collegate contro. Per la cronaca, le librerie includono X11, ZeroC's Ice, Player/Stage e OpenCV (con quest'ultimo 2 compilato manualmente con le dipendenze installate tramite MacPorts). Sembra che sia l'inclusione di OpenCV a causare il problema, dal momento che altre librerie che si collegano a tutte queste eccetto OpenCV possono essere caricate senza problemi. Questi sono i miei sospetti, ma al momento mi manca il know-how per approfondire ulteriormente.

Grazie! Nick

AGGIORNAMENTO: Grazie alla risposta di Kaelin (le opzioni di DYLD_PRINT_ * di cui non ero a conoscenza in precedenza) sono stato in grado di confermare almeno che non stava accadendo nulla di completamente ovvio. Usando le informazioni di debug sono stato in grado di restringere il problema a una particolare libreria che stava causando l'arresto. Si è scoperto che questa libreria (libdc1394 collegata alla mia app tramite libhighgui in OpenCV) non era correttamente collegata a CoreServices e questo causava l'arresto anomalo. Per qualche motivo l'errore è stato quindi nascosto da altre cose, causando il crash finale. Per informazioni sul problema libdc1394, vedi here. Sfortunatamente non sono riuscito a fare una correzione pulita che posso segnalare qui, quindi sono riuscito a ottenere una versione dell'applicazione in esecuzione che non si collegava alla libreria dubbia (disattivando libdc1394 nella compilazione OpenCV).

risposta

3

dyld sta eseguendo gli inizializzatori nella libreria condivisa (si pensi agli inizializzatori statici in C++) e uno di questi sta causando l'esecuzione della funzione __CFInitialize del framework CoreFoundation. [È possibile che questa sia la prima cosa che tocca CoreFoundation?] E per qualsiasi ragione, __CFInitialize non è felice. Questo potrebbe essere una sorta di dipendenza mancante. O potrebbe essere l'heap è danneggiato. Oppure potrebbe essere un bug latente di qualche tipo nel framework CoreFoundation.

Suggerirei di ritagliare le prime due possibilità con a) eseguendo tutte le variabili di ambiente DYLD_PRINT_ * impostate [vedere man dyld] eb) in esecuzione in MallocDebug. Se nessuno di questi ha perso la luce, probabilmente ti rimane da scrivere un radar per la gente del CoreFoundation da guardare.

+0

impressionante, grazie. Proverò questi entrambi e vedrò cosa succede. Pubblicherò anche quello che trovo per riferimento futuro. –

7

Dopo alcuni altri problemi e qualche ulteriore ricerca su Google, alla fine ho trovato la vera causa del mio problema.

Uno non può chiamare dlopen una libreria collegata con CoreFoundation in un (sotto) thread se CoreFoundation non è stato inizializzato in primo luogo. CFInitialize è chiamato, apparentemente controlla se il thread è il thread principale e se non lo è, si blocca con un SIGTRAP.

http://openradar.appspot.com/7209349

Problemi correlati