2010-04-06 12 views
11

Je veux utiliser setitimer() (ou moins probable, le alarm()) dans le processus multithread dans Linux 2.6+ avec libc activé NPTL. Quel fil recevra sigalarm (SIGALRM) du noyau?setitimer, SIGALRM & processus multithread (linux, c)

Merci.

Mise à jour 2014-04: Comment définir le setitimer() dans un programme multithread, si je veux écrire un utilitaire de profilage comme cpuprofile de gperftools; mais dans mon outil, je veux prendre en charge les programmes liés dynamiquement (il est donc possible d'injecter ma propre bibliothèque dans le profilage init) et les programmes liés statiquement (sans possibilité de faire ^^^^^^).

Mon outil de profilage actuel fonctionne avec la mise en setitimer juste après fork() et avant exec(), et il utilise également ptrace pour obtenir le contrôle sur le programme cible et de pirater SIGPROF/SIGVPROF/SIGALRM généré par le setitimer. Je n'ai aucune idée exacte de la façon dont cela fonctionne avec les programmes multithread.

+1

est-ce la même chose pour freebsd et solaris? – osgx

Répondre

13

De signal(7) page man:

Un signal dirigé processus peut être délivrée à l'un des fils qui ne dispose pas actuellement le signal bloqué. Si plus de un des fils a le signal débloqué, alors le noyau choisit un thread arbitraire à laquelle fournir le signal.

Maintenant, alarm(2) page de manuel dit que:

alarme() dispose d'un SIGALRM à livrer au processus en secondes secondes.

Ainsi, le signal est délivré à un processus (un signal peut être dirigé à un certain fil trop) et donc vous ne savez pas quel des fils le recevra.

La même chose avec setitimer(2):

Lorsqu'un temporisateur expire, un signal est envoyé à le processus, et la minuterie (potentiellement) redémarre.

Vous pouvez bloquer SIGALARM dans tous vos threads sauf un, alors vous pouvez être sûr qu'il sera livré à ce seul thread. En supposant que vous utilisez pthreads, vous pouvez bloquer les signaux avec pthread_sigmask().

+0

et qu'en est-il de setitimer? – osgx

+0

C'est la même chose pour tous les signaux. – nos

+2

@nos Fondamentalement, mais vous pouvez envoyer des signaux directement à certains threads avec par exemple 'pthread_kill()' – pajton

4

Il était sujet intéressant LKML en 2010 https://lkml.org/lkml/2010/4/11/81: "setitimer vs. fils: SIGALRM retourné à quel thread (maître de processus ou d'un enfant individuel)?" Par Frantisek Rysanek (cz). Auteur dit que setitimer utilisé signaux par thread au moins dans les temps avant Fedora 5:

... setitimer() avait une granularité par fil.Il fournissait un SIGALRM du temporisateur au thread particulier qui appelait setitimer().

Mais plus Fedoras récents le comportement a été modifié ("pthreads homme", ... "Les threads ne partagent pas les compteurs d'intervalle (corrigé dans le noyau 2.6.12).")

Dans le sujet, Andi Kleen (Intel) recommends to switch to "Timers POSIX (timer_create)"; et dans ML thread Davide Libenzi suggère l'utilisation de timerfd (timerfd_create, timerfd_settime) sur des Linux non-anciens.

+0

Googled avec "processus setitimer' thread". Autres pages intéressantes: [Solaris 9] (http://www.shrubbery.net/solaris9ab/SUNWdev/MTP/p34.html) "Lorsque le temporisateur d'intervalle a expiré, SIGVTALRM ou SIGPROF, selon le cas, a été envoyé au LWP possédait le temporisateur d'intervalle. "; [Redhat bug 142790 "Les temporisateurs du processeur setitimer devraient être par processus, pas par thread", 2004] (https://bugzilla.redhat.com/show_bug.cgi?id=142790) "setitimer fonctionne sur des threads individuels, même sous NPTL POSIX dit que cela devrait être à l'échelle du processus. " Envoyer des mails haineux à POSIX et Roland McGrath ("Mes changements sont dans l'arbre de Linus maintenant ... 2.6.12") – osgx

+0

Google-perftools (gperftools) avec cpuprofile devrait avoir les mêmes problèmes avec 'setitimer': https://code.google .com/p/gperftools/"* Problème OS X: dans les programmes multithread, il semble que OS X délivre souvent le signal de profilage (de sigitimer()) au thread principal, même quand il dort, plutôt que de générer des threads vrai travail*"; https://chromium.googlesource.com/external/gperftools/+/8e188310f7d8732d81b7b04f193f89964b7af6c5/src/profiler.cc - "* TODO: Détecte si setitimer() s'applique à tous les threads du processus. *" – osgx

+0

HPUX a un intervalle supplémentaire des temporisateurs avec un comportement bien défini pour les threads: http://www.polarhome.com/service/man/generic.php?qf=setitimer&type=2&of=HP-UX&sf=2 * "De plus ... HP-UX fournit le après trois temporisateurs d'intervalles par thread pour les threads, ... le signal est envoyé au thread ... "* – osgx