Un déroulement forcé non géré provoque un abandon

Par conséquent, si j’ai bien compris pthread_exit et pthread_cancel , ils font en sorte qu’une chose semblable à une exception appelée “retrait forcé” soit éjectée du cadre de stack approprié dans le thread cible. Cela peut être intercepté pour effectuer un nettoyage spécifique à un thread, mais doit être relancé ou nous obtenons un abort() implicite abort() à la fin du bloc catch qui n’a pas été relancé.

Dans le cas de pthread_cancel , cela se produit soit immédiatement après la réception du signal associé, soit lors de la prochaine entrée dans un point d’annulation, ou lors du déblocage suivant du signal, en fonction de l’état et du type d’annulation du thread.

Dans le cas de pthread_exit , le thread appelant subit immédiatement un déroulement forcé.

Bien. Cette “exception” fait partie du processus de suppression d’un thread. Alors pourquoi, même lorsque je le relance, cause-t-il l’appel de std::terminate() , en abandonnant toute mon application?

Notez que je rattrape et relance l’exception à quelques resockets.

Notez également que j’appelle pthread_exit partir de mon gestionnaire de signal SIGTERM . Cela fonctionne très bien dans mon code de test jouet, compilé avec g ++ 4.3.2, qui a un signal(SIGTERM, handler_that_calls_pthread_exit) exécution de thread signal(SIGTERM, handler_that_calls_pthread_exit) , puis signal(SIGTERM, handler_that_calls_pthread_exit) dans une boucle while jusqu’à ce qu’il reçoive le signal TERM . Mais cela ne fonctionne pas dans la vraie application.

Cadres de stack pertinents:

 (gdb) where #0 0x0000003425c30265 in raise () from /lib64/libc.so.6 #1 0x0000003425c31d10 in abort () from /lib64/libc.so.6 #2 0x00000000012b7740 in sv_bsd_terminate () at exception_handlers.cpp:38 #3 0x00002aef65983aa6 in __cxxabiv1::__terminate (handler=0x518) at /view/ken_gcc_4.3/vobs/Comstackr/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:43 #4 0x00002aef65983ad3 in std::terminate () at /view/ken_gcc_4.3/vobs/Comstackr/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:53 #5 0x00002aef65983a5a in __cxxabiv1::__gxx_personality_v0 ( version=, actions=, exception_class=, ue_header=0x645bcd80, context=0x645bb940) at /view/ken_gcc_4.3/vobs/Comstackr/gcc/libstdc++-v3/libsupc++/eh_personality.cc:657 #6 0x00002aef6524d68c in _Unwind_ForcedUnwind_Phase2 (exc=0x645bcd80, context=0x645bb940) at /view/ken_gcc_4.3/vobs/Comstackr/gcc/libgcc/../gcc/unwind.inc:180 #7 0x00002aef6524d723 in _Unwind_ForcedUnwind (exc=0x645bcd80, stop=, stop_argument=0x645bc1a0) at /view/ken_gcc_4.3/vobs/Comstackr/gcc/libgcc/../gcc/unwind.inc:212 #8 0x000000342640cf80 in __pthread_unwind () from /lib64/libpthread.so.0 #9 0x00000034264077a5 in pthread_exit () from /lib64/libpthread.so.0 #10 0x0000000000f0d959 in threadHandleTerm (sig=) at osiThreadLauncherLinux.cpp:46 #11  

Merci!

Eric

Notez également que j’appelle pthread_exit à partir de mon gestionnaire de signal SIGTERM.

C’est ton problème. Pour citer les spécifications POSIX (http://pubs.opengroup.org/onlinepubs/009695399/functions/signal.html):

Si le signal survient autrement que suite à l’appel de abort (), raise (), kill (), pthread_kill () ou sigqueue (), le comportement n’est pas défini si le gestionnaire de signal fait référence à un object dont la durée de stockage statique est en atsortingbuant une valeur à un object déclaré comme volatil sig_atomic_t, ou si le gestionnaire de signaux appelle une fonction de la bibliothèque standard autre que l’une des fonctions répertoriées dans les concepts de signal.

La liste des fonctions autorisées est donnée sur http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html#tag_02_04_03 et n’inclut pas pthread_exit() . Par conséquent, votre programme présente un comportement indéfini.

Je peux penser à trois choix:

  1. Définissez un indicateur dans le gestionnaire de signaux qui est vérifié périodiquement par le thread, plutôt que d’essayer de sortir directement du gestionnaire de signaux.
  2. Utilisez sigwait() pour attendre explicitement le signal sur un thread indépendant. Ce thread peut ensuite appeler explicitement pthread_cancel() sur le thread que vous souhaitez quitter.
  3. sigpending() le signal et appelez sigpending() périodiquement sur le thread à quitter, puis quittez-le si le signal est en attente.