2010-08-05 27 views
7

J'ai un problème avec une application C++ que j'ai développée et qui utilise dlopen pour charger des bibliothèques développées par l'utilisateur. L'application a été utilisée par une variété de personnes sur une variété de distributions Linux et de versions d'OSX au cours des dernières années et donc je suppose que mon utilisation de dlopen est OK et le code qui en dépend (oui, c'est de l'hubris, donc je rapporterai quand ça échouera). Le problème que j'ai maintenant est qu'un utilisateur a développé une bibliothèque qui ne charge pas sur mon système (OSX 10.6.4). Lorsque le système essaie de le charger, il y a un gel puis un crash. Le fil qui plante ressemble à ceci dans le rapport de l'accident:Déboguer un plantage lorsqu'une bibliothèque est ouverte via dlopen sous 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 

(je peux poster le journal complet si nécessaire, mais il dépasse la limite de corps du texte si je l'inclus dans mon post)

Dans le terminal où j'exécute l'exécutable le crash ne produit aucune sortie sauf pour la notification que le script exécutant l'exécutable a piégé un signal.

Ma question est Comment puis-je obtenir plus d'informations sur ce qui pourrait causer ce plantage? Je suis également heureux si quelqu'un peut suggérer des solutions possibles, mais pour commencer, j'aimerais au moins savoir comment générer plus d'informations lorsque le système se bloque sur ce qui est réellement faux.

Si je lance otool sur la bibliothèque qui est en cours d'ouverture par dlopen, tout semble correct (pas de liens, symboles, etc.). Ma principale suspicion est que c'est la combinaison particulière de bibliothèques avec laquelle la bibliothèque chargée est liée, qui est à l'origine de ce crash. Ces autres bibliothèques peuvent être chargées en utilisant différents sous-ensembles de ces bibliothèques liées. Pour mémoire les librairies incluent X11, Ice, ZeroC's, Player/Stage et OpenCV (avec les 2 derniers compilés manuellement avec les dépendances installées avec MacPorts). Il semble que c'est l'inclusion d'OpenCV qui cause le problème, car d'autres bibliothèques qui sont reliées à tous, sauf OpenCV, peuvent être chargées sans problèmes. Ce sont mes soupçons, mais je n'ai pas le savoir-faire pour approfondir.

Merci! Nick

MISE À JOUR: Grâce à la réponse de Kaelin (les options DYLD_PRINT_ * dont je n'étais pas au courant), j'ai pu au moins confirmer que rien de complètement évident ne se produisait. En utilisant les informations de débogage, j'ai été capable de réduire le problème à une bibliothèque particulière qui causait le crash. Il s'est avéré que cette bibliothèque (libdc1394 liée à mon application via libhighgui dans OpenCV) n'était pas correctement liée à CoreServices et que cela causait le crash. Pour une raison quelconque, l'erreur a ensuite été cachée par d'autres choses, causant le crash ultime. Pour plus d'informations sur le problème libdc1394, regardez here. Malheureusement, je ne pouvais pas faire une correction propre que je puisse rapporter ici, donc j'ai juste réussi à faire tourner une version de l'application qui ne soit pas liée à la bibliothèque douteuse (en désactivant libdc1394 dans la compilation OpenCV).

Répondre

3

dyld exécute les initialiseurs dans la bibliothèque partagée (pensez aux initialiseurs statiques en C++), et l'un d'eux provoque l'exécution de la fonction __CFInitialize du framework CoreFoundation. [Est-il possible que ce soit la première chose qui touche à CoreFoundation?] Et pour une raison quelconque, __CFInitialize n'est pas content. Cela pourrait être une sorte de dépendance manquante. Ou il pourrait être le tas est corrompu. Ou il pourrait s'agir d'un bug latent quelconque dans le framework CoreFoundation.

Je suggère de rogner les deux premières possibilités en a) s'exécutant avec tous les DYLD_PRINT_ * jeu de variables d'environnement [voir man dyld] et b) sous MallocDebug. Si aucun d'entre eux ne fait la lumière, il vous reste probablement à écrire un radar pour les gens de CoreFoundation à regarder.

+0

Impressionnant, merci. Je vais essayer les deux et voir ce qui se passe. Je posterai aussi ce que je trouve pour référence future. –

7

Après quelques autres problèmes et quelques autres Google, j'ai finalement trouvé la véritable cause de mon problème.

On ne peut pas appeler dlopen une bibliothèque liée à CoreFoundation dans un (sous) thread si CoreFoundation n'a pas été initialisé en premier lieu. CFInitialize est appelée, vérifie apparemment si le thread est le thread principal et si ce n'est pas le cas, se bloque avec un SIGTRAP.

http://openradar.appspot.com/7209349