Provided by: manpages-fr-dev_3.65d1p1-1_all bug

NOM

       ptrace - Suivre un processus

SYNOPSIS

       #include <sys/ptrace.h>

       long ptrace(enum __ptrace_request request, pid_t pid,
                   void *addr, void *data);

DESCRIPTION

       L'appel système ptrace() fournit à un processus (l'« observateur ») un moyen d'observer et
       contrôler l'exécution d'un autre processus (l'« observé »)  et  d'examiner  et  éditer  la
       mémoire  et  les  registres  de  l'observé. L'utilisation principale de cette fonction est
       l'implémentation de points d'arrêt pour le débogage, et pour suivre les appels système.

       Un observé doit d'abord être attaché  à  l'observateur.  L'attachement  et  les  commandes
       suivantes  sont  par  thread :  dans  un  processus  multithreadé, chaque thread peut être
       attaché individuellement à un  observateur  (éventuellement  différent),  ou  être  laissé
       détaché  et  donc  non  débogué.  Par  conséquent,  l'« observé » signifie toujours « (un)
       thread », jamais « un processus (éventuellement multithreadé) ». Les commandes ptrace sont
       toujours envoyées à un observé spécifique en utilisant un appel de la forme

           ptrace(PTRACE_truc, pid, ...)

       où pid est l'identifiant de thread du thread Linux correspondant.

       (Remarquez  que  dans  cette  page,  un  « processus  multithreadé » signifie un groupe de
       threads constitué de threads créés en utilisant l'attribut CLONE_THREAD de clone(2).)

       Un processus peut démarrer un suivi en appelant fork(2) et faire en sorte que le fils créé
       fasse un PTRACE_TRACEME, suivi (en général) par un execve(2). Autrement, un processus peut
       commencer à suivre un autre processus en utilisant PTRACE_ATTACH ou PTRACE_SEIZE.

       L'observé s'arrêtera à chaque fois qu'un signal lui sera distribué, même si le signal  est
       ignoré (à l'exception de SIGKILL qui a les effets habituels). L'observateur sera prévenu à
       son prochain appel de waitpid(2) (ou un des appels système liés à  « wait ») ;  cet  appel
       renverra  une valeur status contenant les renseignements indiquant la raison de l'arrêt de
       l'observé. Lorsque l'observé est arrêté, l'observateur peut  utiliser  plusieurs  requêtes
       ptrace  pour  inspecter  et  modifier  l'observé.  L'observateur  peut  également  laisser
       continuer l'exécution de l'observé, en ignorant éventuellement le signal  ayant  déclenché
       l'arrêt, ou même en envoyant un autre signal.

       Si  l'option  PTRACE_O_TRACEEXEC  n'est pas effective, tous les appels réussis d'execve(2)
       par le processus suivi déclencheront l'envoi d'un signal SIGTRAP, ce qui permet au père de
       reprendre le contrôle avant que le nouveau programme commence son exécution.

       Quand  l'observateur a fini le suivi, il peut forcer l'observé à continuer normalement, en
       mode non suivi, avec PTRACE_DETACH.

       La valeur de l'argument request indique précisément l'action à entreprendre.

       PTRACE_TRACEME
              Le processus en cours va être suivi par son père.  Un  processus  ne  devrait  sans
              doute  pas envoyer cette requête si son père n'est pas prêt à le suivre. Dans cette
              requête pid, addr, et data sont ignorés.

              La requête PTRACE_TRACEME ne sert qu'à l'observé. Les requêtes restantes ne servent
              qu'à  l'observateur. Par la suite, pid précise l'identifiant de thread de l'observé
              sur lequel agir. Pour les  requêtes  différentes  de  PTRACE_ATTACH,  PTRACE_SEIZE,
              PTRACE_INTERRUPT et PTRACE_KILL, l'observé doit être arrêté.

       PTRACE_PEEKTEXT, PTRACE_PEEKDATA
              Lire  un  mot à l'adresse addr dans l'espace mémoire de l'observé et le renvoyer en
              résultat de l'appel ptrace(). Linux ne sépare pas les espaces d'adressage  de  code
              et de données, donc ces deux requêtes sont équivalentes (data est ignoré, consultez
              la section NOTES).

       PTRACE_PEEKUSER
              Lire un mot à la position addr dans l'espace USER de l'observé,  qui  contient  les
              registres  et divers renseignements sur le processus (voir <sys/user.h>). La valeur
              est renvoyée en résultat de ptrace(). En principe, l'adresse doit être alignée  sur
              une  frontière  de  mots, bien que cela varie selon les architectures. Consultez la
              section NOTES. (data est ignoré, consultez la section NOTES).

       PTRACE_POKETEXT, PTRACE_POKEDATA
              Copier un mot depuis l'adresse data de la mémoire de l'observateur  vers  l'adresse
              addr de la mémoire de l'observé. Comme pour PTRACE_PEEKTEXT et PTRACE_PEEKDATA, ces
              deux requêtes sont équivalentes.

       PTRACE_POKEUSER
              Copier un mot depuis  l'emplacement  data  de  la  mémoire  de  l'observateur  vers
              l'emplacement addr dans l'espace USER de l'observé. Comme pour PTRACE_PEEKUSER, les
              emplacements doivent  être  alignés  sur  une  frontière  de  mot.  Pour  maintenir
              l'intégrité du noyau, certaines modifications de la zone USER sont interdites.

       PTRACE_GETREGS, PTRACE_GETFPREGS
              Copier  les  registres généraux ou du processeur en virgule flottante de l'observé,
              vers l'adresse data de l'observateur. Consultez <sys/user.h> pour les  détails  sur
              le format de ces données (addr est ignoré). Remarquez que les systèmes SPARC ont la
              signification de data et addr inversée, c'est-à-dire que data  est  ignoré  et  les
              registres  sont  copiés  vers l'adresse addr. PTRACE_GETREGS et PTRACE_GETFPREGS ne
              sont pas présents sur toutes les architectures.

       PTRACE_GETREGSET (depuis Linux 2.6.34)
              Lire  les  registres  de  l'observé.  addr  indique,  de  manière   dépendante   de
              l'architecture, le type de registres à lire. NT_PRSTATUS (avec une valeur numérique
              de 1) a pour conséquence  habituelle  la  lecture  de  registres  généraux.  Si  le
              processeur  a,  par  exemple, des registres en virgule flottante ou en vecteur, ils
              peuvent être récupéré en configurant addr à  la  constante  NT_foo  correspondante.
              data  pointe vers une struct iovec, qui décrit l'emplacement et la taille du tampon
              de destination. Le noyau modifie iov.len  au  retour  pour  indiquer  le  véritable
              nombre d'octets renvoyés.

       PTRACE_SETREGS, PTRACE_SETFPREGS
              Modifier les registres généraux ou du processeur en virgule flottante de l'observé,
              depuis l'adresse data  de  l'observateur.  Comme  pour  PTRACE_POKEUSER,  certaines
              modifications  de  registres généraux pourraient être interdites (addr est ignoré).
              Remarquez que les systèmes SPARC ont la signification de  data  et  addr  inversée,
              c'est-à-dire  que  data  est  ignoré  et les registres sont copiés depuis l'adresse
              addr. PTRACE_SETREGS et PTRACE_SETFPREGS  ne  sont  pas  présents  sur  toutes  les
              architectures.

       PTRACE_SETREGSET (depuis Linux 2.6.34)
              Modifier  les registres de l'observé. La signification de addr et data est analogue
              à PTRACE_GETREGSET.

       PTRACE_GETSIGINFO (depuis Linux 2.3.99-pre6)
              Récupérer des renseignements sur le signal qui a provoqué l'arrêt. Pour  ce  faire,
              copier  une  structure  siginfo_t (consultez sigaction(2)) de l'observé à l'adresse
              data de l'observateur (addr est ignoré).

       PTRACE_SETSIGINFO (depuis Linux 2.3.99-pre6)
              Définir les renseignements de signaux : copier une structure siginfo_t de l'adresse
              data  de  l'observateur vers l'observé. Cela n'affecte que les signaux qui auraient
              dû être distribués à  l'observé  et  ont  été  interceptés  à  cause  de  ptrace().
              Différencier  ces signaux normaux des signaux créés par ptrace() lui-même peut être
              délicat (addr est ignoré).

       PTRACE_PEEKSIGINFO (depuis Linux 3.10)
              Récupérer les structures siginfo_t sans supprimer les signaux d’une file d’attente.
              addr  pointe  vers  une  structure  ptrace_peeksiginfo_args qui indique la position
              ordinale à partir de laquelle la copie des signaux devrait commencer et  le  nombre
              de  signaux  à  copier. Les structures siginfo_t sont copiées dans le tampon pointé
              par data. La valeur de retour contient le nombre de signaux  copiés  (zéro  indique
              qu’il  n’y a pas de signal correspondant à la position ordinale indiquée). Dans les
              structures  siginfo  renvoyées,  le  champ  si_code  contient  des   renseignements
              (__SI_CHLD, __SI_FAULT, etc.) qui ne sont sinon pas exposés à l’espace utilisateur.

                 struct ptrace_peeksiginfo_args {
                     u64 off;    /* Position ordinale dans la file d’attente
                                    où commencer la copie de signaux */
                     u32 flags;  /* PTRACE_PEEKSIGINFO_SHARED ou 0 */
                     s32 nr;     /* Nombre de signaux à copier */
                 };

                 Actuellement,  seul  l’attribut  PTRACE_PEEKSIGINFO_SHARED  permet  de vider les
                 signaux de la file de signaux par processus. Si cet attribut n’est  pas  défini,
                 les signaux sont lus depuis la file par thread du thread indiqué.

       PTRACE_GETSIGMASK (depuis Linux 3.11)
              Placer  une  copie du masque des signaux bloqués (consultez sigprocmask(2)) dans le
              tampon pointé par data qui  devrait  être  un  pointeur  vers  un  tampon  de  type
              sigset_t.   L’argument   addr   contient  la  taille  du  tampon  pointé  par  data
              (c’est-à-dire sizeof(sigset_t)).

       PTRACE_SETSIGMASK (depuis Linux 3.11)
              Modifier le masque des signaux  bloqués  (consultez  sigprocmask(2))  à  la  valeur
              indiquée dans le tampon pointé par data qui devrait être un pointeur vers un tampon
              de type sigset_t. L’argument addr contient la taille  du  tampon  pointé  par  data
              (c’est-à-dire sizeof(sigset_t)).

       PTRACE_SETOPTIONS (depuis Linux 2.4.6, consultez les remarques de BOGUES)
              Définir  les  options  de ptrace à partir de l'adresse data (addr est ignoré). data
              est interprété comme un masque d'options, qui est construit à partir des  attributs
              suivants.

              PTRACE_O_EXITKILL (depuis Linux 3.8)
                     Si  l'observateur définit cet attribut, un signal SIGKILL sera envoyé à tous
                     les observés quand l'observateur se termine. Cet option est utile  pour  les
                     gardiens  ptrace  qui  veulent  s'assurer que les observés ne peuvent jamais
                     échapper au contrôle de l'observateur.

              PTRACE_O_TRACECLONE (depuis Linux 2.5.46)
                     Arrêter l'observé au prochain clone(2) et commencer automatiquement à suivre
                     le  nouveau  processus  cloné,  qui  démarrera  avec  un  signal SIGSTOP, ou
                     PTRACE_EVENT_STOP  si  PTRACE_SEIZE   est   utilisé.   Un   waitpid(2)   par
                     l'observateur renverra une valeur status comme

                       status>>8 == (SIGTRAP | (PTRACE_EVENT_CLONE<<8))

                     Le PID du nouveau processus peut être récupéré avec PTRACE_GETEVENTMSG.

                     Cette  option peut ne pas intercepter tous les appels clone(2). Si l'observé
                     appelle clone(2) avec l'attribut CLONE_VFORK, PTRACE_EVENT_VFORK sera envoyé
                     si  PTRACE_O_TRACEVFORK  est  utilisé.  Sinon, si l'observé appelle clone(2)
                     avec SIGCHLD comme signal de terminaison, PTRACE_EVENT_FORK sera  envoyé  si
                     PTRACE_O_TRACEFORK est utilisé.

              PTRACE_O_TRACEEXEC (depuis Linux 2.5.46)
                     Arrêter  l'observé  au  prochain  execve(2). Un waitpid(2) par l'observateur
                     renverra une valeur status comme

                       status>>8 == (SIGTRAP | (PTRACE_EVENT_EXEC<<8))

                     Si le thread en cours d'exécution n'est pas un leader de groupe de  threads,
                     l'identifiant de thread est réinitialisé à l'identifiant du leader de groupe
                     de threads avant cet arrêt. Depuis  Linux 3.0,  le  premier  identifiant  de
                     thread peut être récupéré avec PTRACE_GETEVENTMSG.

              PTRACE_O_TRACEEXIT (depuis Linux 2.5.60)
                     Arrêter l'observé à la terminaison. Un waitpid(2) par l'observateur renverra
                     une valeur status comme

                       status>>8 == (SIGTRAP | (PTRACE_EVENT_EXIT<<8))

                     L'état de fin de l'observé peut être récupéré avec PTRACE_GETEVENTMSG.

                     L'observé est arrêté tôt dans la terminaison du  processus,  alors  que  les
                     registres  sont  toujours  disponibles, ce qui permet au processus utilisant
                     ptrace() de voir où la terminaison s'est produite, alors que la notification
                     de  terminaison  normale  a  lieu  à la fin de cette terminaison. Même si le
                     contexte est disponible, l'observateur ne peut pas empêcher la terminaison à
                     ce moment là.

              PTRACE_O_TRACEFORK (depuis Linux 2.5.46)
                     Arrêter  l'observé au prochain fork(2) et commencer automatiquement à suivre
                     le nouveau  processus  créé,  qui  démarrera  avec  un  signal  SIGSTOP,  ou
                     PTRACE_EVENT_STOP   si   PTRACE_SEIZE   est   utilisé.   Un  waitpid(2)  par
                     l'observateur renverra une valeur status comme

                       status>>8 == (SIGTRAP | (PTRACE_EVENT_FORK<<8))

                     Le PID du nouveau processus peut être récupéré avec PTRACE_GETEVENTMSG.

              PTRACE_O_TRACESYSGOOD (depuis Linux 2.4.6)
                     Lors des interceptions d'appel système, mettre à 1 le  bit 7  du  numéro  de
                     signal (envoyer SIGTRAP | 0x80). Cela permet au processus utilisant ptrace()
                     de faire la différence entre les interceptions normales et celles provoquées
                     par  un  appel  système.  PTRACE_O_TRACESYSGOOD  peut ne pas fonctionner sur
                     toutes les architectures.

              PTRACE_O_TRACEVFORK (depuis Linux 2.5.46)
                     Arrêter l'observé au prochain vfork(2) et commencer automatiquement à suivre
                     le  nouveau  processus  créé,  qui  démarrera  avec  un  signal  SIGSTOP, ou
                     PTRACE_EVENT_STOP  si  PTRACE_SEIZE   est   utilisé.   Un   waitpid(2)   par
                     l'observateur renverra une valeur status comme

                       status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK<<8))

                     Le PID du nouveau processus peut être récupéré avec PTRACE_GETEVENTMSG.

              PTRACE_O_TRACEVFORKDONE (depuis Linux 2.5.60)
                     Arrêter  l'observé  à  la  fin  du  prochain  vfork(2).  Un  waitpid(2)  par
                     l'observateur renverra une valeur status comme

                       status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK_DONE<<8))

                     Le PID du nouveau processus peut (depuis Linux 2.6.18)  être  récupéré  avec
                     PTRACE_GETEVENTMSG.

       PTRACE_GETEVENTMSG (depuis Linux 2.5.46)
              Récupérer  un  message  (dans  un  unsigned long) concernant l'événement ptrace qui
              vient  d'arriver,  en  le  plaçant  à  l'adresse  data   de   l'observateur.   Pour
              PTRACE_EVENT_EXIT,   il   s'agit   du   code   de   retour   de   l'observé.   Pour
              PTRACE_EVENT_FORK,       PTRACE_EVENT_VFORK,       PTRACE_EVENT_VFORK_DONE       et
              PTRACE_EVENT_CLONE, il s'agit du PID du nouveau processus (addr est ignoré).

       PTRACE_CONT
              Redémarrer l'observé arrêté. Si data est non nul, il est interprété comme un numéro
              de  signal  à  distribuer  à  l'observé ;  sinon  aucun  signal  n'est   distribué.
              L'observateur  peut  ainsi  contrôler si un signal envoyé à l'observé doit lui être
              distribué ou non (addr est ignoré).

       PTRACE_SYSCALL, PTRACE_SINGLESTEP
              Redémarrer l'observé arrêté comme pour PTRACE_CONT, mais en s'arrangeant pour qu'il
              soit  arrêté  à  la  prochaine  entrée  ou  sortie  d'un appel système, ou après la
              prochaine instruction, respectivement (l'observé sera aussi  arrêté  par  l'arrivée
              d'un  signal). Du point de vue de l'observateur, l'observé semblera être arrêté par
              SIGTRAP. Ainsi, pour PTRACE_SYSCALL l'idée est d'inspecter les arguments de l'appel
              système  au  premier  arrêt puis de faire un autre PTRACE_SYSCALL et d'inspecter la
              valeur de retour au second arrêt. Le  paramètre  data  est  interprété  comme  pour
              PTRACE_CONT (addr est ignoré).

       PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP (depuis Linux 2.6.14)
              Pour PTRACE_SYSEMU, continuer puis s'arrêter lors du prochain appel système, qui ne
              sera pas exécuté. Pour PTRACE_SYSEMU_SINGLESTEP, faire la même chose, mais exécuter
              pas  à  pas  s'il ne s'agit pas d'un appel système. Cette fonction est utilisée par
              des programmes comme User Mode Linux, qui veulent émuler tous les appels système de
              l'observé. Le paramètre data est interprété comme pour PTRACE_CONT. L'argument addr
              est ignoré. Ces requêtes ne sont pour l'instant disponibles que sur x86.

       PTRACE_LISTEN (depuis Linux 3.4)
              Redémarrer l'observé arrêté, mais en l'empêchant de s'exécuter. L'état résultant de
              l'observé  est similaire a celui d'un processus qui a été arrêté par un SIGSTOP (ou
              autre  signal  d'arrêt).  Consultez   la   sous-section   Arrêt-groupe   pour   des
              renseignements  supplémentaires.  PTRACE_LISTEN  ne fonctionne que sur les observés
              attachés par PTRACE_SEIZE.

       PTRACE_KILL
              Envoyer à l'observé un signal SIGKILL pour le terminer (addr et data sont ignorés).

              Cette opération est obsolète, ne l'utilisez pas. À la  place,  envoyez  un  SIGKILL
              directement  en  utilisant  kill(2)  ou tgkill(2). Le problème avec PTRACE_KILL est
              qu'il nécessite que l'observé soit en arrêt-distribution-signal, sinon cela  risque
              de  ne  pas  fonctionner  (c'est-à-dire risque de se terminer avec succès sans tuer
              l'observé). En revanche, envoyer SIGKILL directement n'est pas concerné  par  cette
              limite.

       PTRACE_INTERRUPT (depuis Linux 3.4)
              Arrêter  un  observé.  Si  l’observé  est  en  cours d’exécution ou en sommeil dans
              l’espace utilisateur et  que  PTRACE_SYSCALL  est  effectif,  l’appel  système  est
              interrompu  et l'arrêt-sortie-appel-système est signalé (l’appel système interrompu
              est redémarré quand l’observé est redémarré). Si l’observé avait  déjà  été  arrêté
              par  un  signal  et que PTRACE_LISTEN lui avait été envoyé, l’observé s’arrête avec
              PTRACE_EVENT_STOP et WSTOPSIG(status) renvoie le signal d’arrêt. Si n’importe  quel
              autre  arrêt-ptrace  est créé en même temps (par exemple, si un signal est envoyé à
              l’observé), cet arrêt-ptrace arrive. Si rien de ce qui précède ne  s’applique  (par
              exemple  si  l’observé est en cours d’exécution en espace utilisateur), il s’arrête
              avec  PTRACE_EVENT_STOP  avec  WSTOPSIG(status)  ==  SIGTRAP.  PTRACE_INTERRUPT  ne
              fonctionne que sur les observés attachés par PTRACE_SEIZE.

       PTRACE_ATTACH
              Attacher le processus numéro pid, pour le suivre. L'observé va recevoir un SIGSTOP,
              mais il ne sera peut-être  pas  arrêté  tout  de  suite,  utilisez  waitid(2)  pour
              attendre  son  arrêt.  Consultez  la  sous-section  Attachement et détachement pour
              obtenir de plus amples renseignements (addr et data sont ignorés).

       PTRACE_SEIZE (depuis Linux 3.4)
              Attacher au processus indiqué par  pid,  faisant  de  lui  l'observé  du  processus
              appelant.  Contrairement  à  PTRACE_ATTACH, PTRACE_SEIZE n'arrête pas le processus.
              Seul un processus sous PTRACE_SEIZE peut accepter les commandes PTRACE_INTERRUPT et
              PTRACE_LISTEN.  addr  doit être zéro. data contient un masque d'options de ptrace à
              activer immédiatement.

       PTRACE_DETACH
              Relancer l'observé arrêté comme avec  PTRACE_CONT,  mais  en  commençant  par  s'en
              détacher.  Sous  Linux  un  observé peut être détaché ainsi quelque soit la méthode
              employée pour démarrer le suivi (addr est ignoré).

   Mort sous ptrace
       Quand un processus (éventuellement multithreadé) reçoit un signal pour le tuer (un dont la
       disposition  est  configurée  à  SIG_DFL  et  dont  l'action  par  défaut  est  de tuer le
       processus), tous les threads se terminent. Chaque observé signale sa mort  à  son  ou  ses
       observateurs. La notification de cet événement est distribuée par waitpid(2).

       Remarquez que le signal tueur provoquera d'abord un arrêt-distribution-signal (sur un seul
       observé) et, seulement après être injecté par l'observateur (ou après  être  envoyé  à  un
       thread  qui  n'est  pas  suivi),  la  mort  du  signal arrivera sur tous les observés d'un
       processus multithreadé (le terme « arrêt-distribution-signal » est expliqué plus bas).

       SIGKILL ne génère pas d'arrêt-distribution-signal et l'observateur ne peut par  conséquent
       pas    le    supprimer.   SIGKILL   tue   même   à   l'intérieur   des   appels   systèmes
       (arrêt-sortie-appel-système n'est pas créé avant la mort par SIGKILL). L'effet direct  est
       que  SIGKILL  tue  toujours  le  processus (tout ses threads), même si certains threads du
       processus sont suivis avec ptrace.

       Quand l'observé appelle _exit(2), il signale sa mort à son observateur. Les autres threads
       ne sont pas concernés.

       Quand  n'importe  quel  thread  exécute  exit_group(2), tous les observés de son groupe de
       threads signalent leur mort à leur observateur.

       Si l'option PTRACE_O_TRACEEXIT  est  active,  PTRACE_EVENT_EXIT  arrivera  avant  la  mort
       réelle.  Cela  s'applique  aux  terminaisons  avec  exit(2), exit_group(2) et aux morts de
       signal (sauf SIGKILL), et lorsque les threads sont démolis par execve(2) dans un processus
       multithreadé.

       L'observateur  ne peut pas assumer que l'observé arrêté-ptrace existe. L'observé risque de
       mourir avant d'être arrêté dans plusieurs cas (comme avec  SIGKILL).  Par  conséquent,  le
       tracé doit être préparé pour traiter une erreur ESRCH sur n'importe quel opération ptrace.
       Malheureusement,  la  même  erreur  est  renvoyée  si  l'observé  existe  mais  n'est  pas
       arrêté-ptrace  (pour  les  commandes qui nécessitent un observé arrêté), ou s'il n'est pas
       suivi par le processus qui a envoyé l'appel ptrace. L'observateur doit garder une trace de
       l'état  arrêté  ou  en fonctionnement de l'observé, et interpréter ESRCH comme « l'observé
       s'est achevé de manière inattendue » seulement s'il sait que l'observé  est  effectivement
       entré  en  arrêt-ptrace. Remarquez qu'il n'est pas garanti que waitpid(WNOHANG) signale de
       façon fiable  l'état  de  mort  de  l'observé  si  une  opération  ptrace  renvoie  ESRCH.
       waitpid(WNOHANG)  pourrait  plutôt  renvoyer 0. Autrement dit, l'observé pourrait « ne pas
       être encore mort », mais déjà refuser des requêtes ptrace.

       L'observateur ne peut pas assumer  que  l'observé  finit  toujours  sa  vie  en  signalant
       WIFEXITED(status)  ou WIFSIGNALED(status) ; dans certains cas ça n'arrive pas. Par exemple
       si un thread différent du leader de groupe de threads fait un  execve(2),  il  disparaît ;
       son PID ne sera plus jamais vu, tous les arrêts suivants de ptrace seront signalés sous le
       PID du leader de groupe de threads.

   États arrêtés
       Deux états existent pour un observé : en cours d'exécution ou à l'arrêt. Du point  de  vue
       de ptrace, un observé qui est bloqué dans un appel système (comme read(2), pause(2), etc.)
       est néanmoins considéré  en  cours  d’exécution,  même  si  l’observé  est  bloqué  depuis
       longtemps. L’état de l’observé après PTRACE_LISTEN est en quelque sorte une zone d’ombre :
       il n’est dans aucun arrêt-ptrace (les commandes ptrace n’auront aucun effet sur lui et  il
       distribuera   des  notifications  waitpid(2)),  mais  il  pourrait  aussi  être  considéré
       « arrêté »  parce  qu’il  n’est  pas  en  train  d’exécuter  des  instructions   (pas   de
       programmation)  et, s’il était en arrêt-groupe avant PTRACE_LISTEN, il ne répondra pas aux
       signaux avant de recevoir SIGCONT.

       De nombreuses sortes d'états sont possibles quand l'observé est arrêté, et les discussions
       dans  ptrace  sont  souvent confondues. Par conséquent, l'utilisation de termes précis est
       importante.

       Dans cette page de manuel, tous les états d'arrêt  dans  lesquels  l'observé  est  prêt  à
       accepter   des   commandes   ptrace  de  l'observateur  sont  appelés  arrêts-ptrace.  Les
       arrêts-ptrace   peuvent   ensuite   être   sous-divisés   en    arrêt-distribution-signal,
       arrêt-groupe,   arrêt-appel-système, etc.   Ces  états  d'arrêt  sons  décrits  en  détail
       ci-dessous.

       Lorsque l'observé en cours d'exécution entre en arrêt-ptrace, il avise son observateur  en
       utilisant  waitpid(2) (ou un des autres appels système « wait »). La plupart de cette page
       de manuel suppose que l'observateur attend avec :

           pid = waitpid(pid_ou_moins_1, &status, __WALL);

       Les observés arrêtés-ptrace sont signalés comme renvoyés avec un pid  strictement  positif
       et WIFSTOPPED(status) vrai.

       L'attribut  __WALL  ne  contient pas les attributs WSTOPPED et WEXITED, mais implique leur
       fonctionnalité.

       La configuration de l'attribut WCONTINUED en appelant waitpid(2)  n'est  pas  conseillée :
       l'état « exécuté » est relatif au processus et l'utiliser peut embrouiller le vrai père de
       l'observé.

       Utiliser l'attribut WNOHANG pourrait forcer waitpid(2)  à  renvoyer  0  (« aucun  résultat
       d'attente  encore  disponible »)  même  si  l'observateur  sait  qu'il devrait y avoir une
       notification. Exemple :

           errno = 0;
           ptrace(PTRACE_CONT, pid, 0L, 0L);
           if (errno == ESRCH) {
               /* l'observé est mort */
               r = waitpid(observé, &status, __WALL | WNOHANG);
               /* r peut encore être 0 ici ! */
           }

       Les sortes d'arrêts-ptrace suivants existent : arrêts-distribution-signal,  arrêts-groupe,
       arrêts  PTRACE_EVENT  et  arrêts-appel-système.  Ils  sont  signalés  par  waitpid(2) avec
       WIFSTOPPED(status) vrai. Ils peuvent être distingués en examinant la valeur status>>8,  et
       en cas d'ambiguïté dans cette valeur, en faisant une requête PTRACE_GETSIGINFO (remarque :
       la macro WSTOPSIG(status) ne peut pas être utilisée pour réaliser  cet  examen,  car  elle
       renvoie la valeur (status>>8) & 0xff.)

   Arrêt-distribution-signal
       Quand  un  processus  (éventuellement  multithreadé)  reçoit  n'importe  quel  signal sauf
       SIGKILL, le noyau choisi un thread arbitraire pour traiter le signal  (si  le  signal  est
       créé  avec tgill(2), le thread cible peut être explicitement choisi par l'appelant). Si le
       thread choisi est suivi, il entre en arrêt-distribution-signal. À ce moment là, le  signal
       n'est  pas  encore  distribué  au  processus,  et peut être supprimé par l'observateur. Si
       l'observateur ne supprime pas le signal, il passe le signal à l'observé lors de la requête
       suivante  de  redémarrage  de  ptrace.  Cette deuxième étape de distribution de signal est
       appelée injection de signal dans cette page de manuel. Remarquez  que  si  le  signal  est
       bloqué,  l'arrêt-distribution-signal  n'arrive  pas  avant  que le signal soit débloqué, à
       l'exception habituelle que SIGSTOP ne peut pas être bloqué.

       L'arrêt-distribution-signal est respecté par l'observateur tant  que  waitpid(2)  retourne
       avec  WIFSTOPPED(status)  vrai,  avec le signal renvoyé par WSTOPSIG(status). Si le signal
       est SIGTRAP, cela pourrait être un  arrêt-ptrace  de  nature  différente ;  consultez  les
       sections  Arrêts-appel-système  et  execve(2)  sous  ptrace  plus bas pour obtenir de plus
       amples précisions. Si WSTOPSIG(status) renvoie un signal d'arrêt, cela  pourrait  être  un
       arrêt-groupe ; voir ci-dessous.

   Injection et suppression de signal
       Après  un  arrêt-distribution-signal  respecté  par  l'observateur,  l'observateur devrait
       redémarrer l'observé avec l'appel

           ptrace(PTRACE_redémarrer, pid, 0, sig)

       où PTRACE_redémarrer est une des requêtes ptrace de redémarrage. Si sig est 0, alors aucun
       signal  n'est  distribué.  Sinon, le signal sig est distribué. Cette opération est appelée
       injection   de   signal   dans   cette   page   de   manuel,   pour   la   distinguer   de
       l'arrêt-distribution-signal.

       La  valeur  de  sig peut être différente de celle de WSTOPSIG(status) : l'observateur peut
       provoquer l'injection d'un autre signal.

       Remarquez qu'un signal supprimé provoque toujours un retour prématuré des appels  système.
       Dans  ce  cas,  les  appels  système seront redémarrés : l'observateur forcera l'observé à
       réexécuter l'appel système interrompu (ou  l'appel  système  restart_syscall(2)  pour  les
       quelques  appels système qui utilisent un autre mécanisme de redémarrage) si l'observateur
       utilise  PTRACE_SYSCALL.  Même  les  appels  système  (comme  poll(2))  qui  ne  sont  pas
       redémarrables  après signal sont redémarré après la suppression du signal ; cependant, des
       bogues du noyau existent et certains appels système échouent  avec  EINTR  même  si  aucun
       signal observable n'est injecté dans l'observé.

       Lors   du   redémarrage   des   commandes   ptrace   émises  dans  d'autres  arrêts-ptrace
       qu'arrêt-distribution-signal, l'injection de signal n'est pas garantie, même  si  sig  est
       non  nul.  Aucune  erreur n'est signalée ; un sig non nul risque simplement d'être ignoré.
       Les utilisateurs de ptrace ne devraient pas essayer de  « créer  un  nouveau  signal »  de
       cette façon : utilisez plutôt tgkill(2).

       Le  fait que des requêtes d'injection de signal puissent être ignorées lors du redémarrage
       de l'observé après des arrêts ptrace qui ne sont pas  des  arrêts-distribution-signal  est
       une  source  de  confusion  pour  les  utilisateurs de ptrace. Un scénario typique est que
       l'observateur remarque un arrêt-groupe, le confonde avec un arrêt-distribution-signal,  et
       redémarre l'observé avec

           ptrace(PTRACE_restart, pid, 0, stopsig)

       dans  le but d'injecter stopsig, alors que stopsig sera ignoré et que l'observé continuera
       de fonctionner.

       Le signal SIGCONT a pour effet de bord de  réveiller  (tous  les  threads  d'un  processus
       arrêté-groupe.  Cet effet de bord arrive avant un arrêt-distribution-signal. L'observateur
       ne peut pas supprimer cet effet de bord (il ne peut que supprimer l'injection  de  signal,
       qui force seulement le gestionnaire de SIGCONT à ne pas être exécuté dans l'observé, si un
       gestionnaire de ce type est installé). En fait, le réveil depuis un arrêt-groupe  pourrait
       être  suivi par un arrêt-distribution-signal pour le ou les signaux différents de SIGCONT,
       s'ils étaient en attente quand SIGCONT a été distribué. Autrement dit, SIGCONT pourrait ne
       pas être le premier signal remarqué par l'observé après avoir été envoyé.

       L'arrêt  de  signaux force (tous les threads d')un processus à entrer en arrêt-groupe. Cet
       effet de bord arrive après une injection de signal, et peut par conséquent  être  supprimé
       par l'observateur.

       Sous Linux 2.4 et les versions précédentes, le signal SIGSTOP ne pouvait pas être injecté.

       PTRACE_GETSIGINFO  peut être utilisé pour récupérer une structure siginfo_t qui correspond
       au signal  distribué.  PTRACE_SETSIGINFO  pourrait  être  utilisé  pour  le  modifier.  Si
       PTRACE_SETSIGINFO a été utilisé pour modifier siginfo_t, le champ si_signo et le paramètre
       sig de la commande de redémarrage doivent correspondre, sinon le résultat est indéfini.

   Arrêt-groupe
       Quand un processus (éventuellement  multithreadé)  reçoit  un  signal  d'arrêt,  tous  les
       threads  s'arrêtent.  Si  certains  threads  sont  suivis,  ils  entrent  en arrêt-groupe.
       Remarquez que le signal d'arrêt provoquera d'abord un  arrêt-distribution-signal  (sur  un
       seul  observé) et, seulement après avoir été injecté par l'observateur (ou après avoir été
       envoyé à un thread qui n'est pas suivi), l'arrêt-groupe sera initié sur tous les  observés
       d'un   processus   multithreadé.  Comme  d'habitude,  tous  les  observés  signalent  leur
       arrêt-groupe séparément à l'observateur correspondant.

       L'arrêt-groupe  est  respecté  par  l'observateur  tant  que  waitpid(2)   retourne   avec
       WIFSTOPPED(status)  vrai,  avec  le  signal  d'arrêt  disponible  par  l'intermédiaire  de
       WSTOPSIG(status). Le même résultat est renvoyé par d'autres classes  d'arrêts-ptrace,  par
       conséquent la méthode conseillée est de réaliser l'appel

           ptrace(PTRACE_GETSIGINFO, pid, 0, &siginfo)

       L'appel  peut  être  évité  si  le signal n'est pas SIGSTOP, SIGTSTP, SIGTTIN ou SIGTTOU ;
       seuls ces quatre signaux sont des signaux d'arrêt. Si l'observateur voit autre  chose,  ce
       ne  peut pas être un arrêt-groupe. Sinon, l'observateur doit appeler PTRACE_GETSIGINFO. Si
       PTRACE_GETSIGINFO échoue avec EINVAL, alors c'est définitivement un arrêt-groupe (d'autres
       codes  d'échec sont possibles, comme ESRCH (« pas de processus de ce type ») si un SIGKILL
       a tué l'observé).

       Si l’observé était attaché en utilisant PTRACE_SEIZE,  un  arrêt-groupe  est  indiqué  par
       PTRACE_EVENT_STOP :   status>>16   ==   PTRACE_EVENT_STOP.   Cela   permet   la  détection
       d’arrêts-groupe sans nécessiter d’appel PTRACE_GETSIGINFO supplémentaire.

       Depuis Linux 2.6.38, après que l'observateur a vu l'arrêt-ptrace de l'observé  et  jusqu'à
       ce  qu'il  le  redémarre  ou  le  tue,  l'observé ne fonctionnera pas, et n'enverra pas de
       notification (sauf mort par SIGKILL) à l'observateur, même si l'observateur entre dans  un
       autre appel waitpid(2).

       Le  comportement  du  noyau  décrit  dans le paragraphe précédent pose un problème avec la
       gestion transparente de signaux d'arrêt. Si l'observateur  redémarre  l'observé  après  un
       arrêt-groupe,  le signal d'arrêt est effectivement ignoré — l'observé ne reste pas arrêté,
       il fonctionne. Si l'observateur ne redémarre pas l'observé avant d'entrer dans le prochain
       waitpid(2),  les  signaux  SIGCONT  suivants ne seront pas signalés à l'observateur ; cela
       pourrait forcer des signaux SIGCONT à être sans effet sur l'observé.

       Depuis Linux 3.4, une méthode permet d'éviter ce problème : à la place de PTRACE_CONT, une
       commande  PTRACE_LISTEN  peut être utilisée pour redémarrer un observé de façon à ce qu'il
       ne s'exécute pas, mais attende un  nouvel  événement  qu'il  peut  signaler  à  l'aide  de
       waitpid(2) (comme s'il était redémarré par un SIGCONT).

   Arrêts PTRACE_EVENT
       Si   l'observateur   configure   des   options   PTRACE_O_TRACE_*,  l'observé  entrera  en
       arrêts-ptrace appelés arrêts PTRACE_EVENT.

       Les arrêts PTRACE_EVENT sont respectés par l'observateur tant que waitpid(2) retourne avec
       WIFSTOPPED(status),  et  que  WSTOPSIG(status)  renvoie SIGTRAP. Un bit supplémentaire est
       configuré dans l'octet le plus haut du mot d'état : la valeur status>>8 sera

           (SIGTRAP | PTRACE_EVENT_truc << 8).

       Les événements suivants existent.

       PTRACE_EVENT_VFORK
              Arrêt avant de revenir de vfork(2) ou clone(2) avec l'attribut  CLONE_VFORK.  Quand
              l'observé est continué après cet arrêt, il attendra une sortie ou exécution du fils
              avant de continuer son  exécution  (autrement  dit,  le  comportement  normal  avec
              vfork(2)).

       PTRACE_EVENT_FORK
              Arrêt  avant de revenir de fork(2) ou clone(2) avec le signal de sortie configuré à
              SIGCHLD.

       PTRACE_EVENT_CLONE
              Arrêt avant de revenir de clone(2).

       PTRACE_EVENT_VFORK_DONE
              Arrêt avant de revenir de vfork(2) ou clone(2) avec  l'attribut  CLONE_VFORK,  mais
              après que le fils a débloqué son observé par sortie ou exécution.

       Pour  les  quatre  arrêts  décrits  ci-dessus,  l'arrêt  arrive dans le père (c'est-à-dire
       l'observé), pas dans le  nouveau  thread  créé.  PTRACE_GETEVENTMSG  permet  de  récupérer
       l'identifiant du nouveau thread.

       PTRACE_EVENT_EXEC
              Arrêt  avant le retour d'execve(2). Depuis Linux 3.0, PTRACE_GETEVENTMSG renvoie le
              premier identifiant de thread.

       PTRACE_EVENT_EXIT
              Arrêt avant la sortie (y compris la mort depuis exit_group(2)), la mort  du  signal
              ou   la   sortie   provoquée   par   execve(2)   dans  un  processus  multithreadé.
              PTRACE_GETEVENTMSG renvoie l'état de sortie. Les registres  peuvent  être  examinés
              (contrairement à quand une « vraie » sortie arrive). L'observé est toujours actif ;
              il a besoin de PTRACE_CONT ou PTRACE_DETACH pour terminer sa sortie.

       PTRACE_EVENT_STOP
              Arrêt causé par la commande  PTRACE_INTERRUPT,  ou  arrêt-groupe,  ou  arrêt-ptrace
              initial  quand un nouveau fils est attaché (seulement s’il est attaché en utilisant
              PTRACE_SEIZE), ou PTRACE_EVENT_STOP si PTRACE_SEIZE était utilisé.

       PTRACE_GETSIGINFO sur les arrêts PTRACE_EVENT renvoie SIGTRAP dans si_signo, avec  si_code
       configuré à (event<<8) | SIGTRAP.

   Arrêts-appel-système
       Si    l'observé    était    redémarré    par    PTRACE_SYSCALL,    l'observé    entre   en
       arrêt-entrée-appel-système juste avant d'entrer dans  n'importe  quel  appel  système.  Si
       l'observateur    redémarre    l'observé    avec   PTRACE_SYSCALL,   l'observé   entre   en
       arrêt-sortie-appel-système quand l'appel système est terminé, ou s'il est  interrompu  par
       un   signal   (c'est-à-dire  qu'un  arrêt-distribution-signal  n'arrive  jamais  entre  un
       arrêt-entrée-appel-système   et   un   arrêt-sortie-appel-système :   il   arrive    après
       l'arrêt-sortie-appel-système).

       D'autres  possibilités  sont  que l'observé pourrait s'arrêter dans un arrêt PTRACE_EVENT,
       sortir (s'il est entré en _exit(2) ou exit_group(2)),  être  tué  par  SIGKILL  ou  mourir
       silencieusement  (s'il s'agit d'un leader de groupe de threads, que l'execve(2) est arrivé
       dans un autre thread et que ce thread n'est pas suivi  par  le  même  observateur ;  cette
       situation sera abordée plus tard).

       Les   arrêt-entrée-appel-système   et   arrêt-sortie-appel-système   sont   respectés  par
       l'observateur  tant  que  waitpid(2)  retourne  avec  WIFSTOPPED(status)  vrai,   et   que
       WSTOPSIG(status)  donne  SIGTRAP.  Si  l'option PTRACE_O_TRACESYSGOOD était configurée par
       l'observateur, alors WSTOPSIG(status) donnera la valeur (SIGTRAP | 0x80).

       Les arrêts-appel-système  peuvent  être  distingués  d'un  arrêt-distribution-signal  avec
       SIGTRAP en demandant PTRACE_GETSIGINFO pour les cas suivants.

       si_code <= 0
              SIGTRAP  a  été  distribué  comme  résultat d'une action en espace utilisateur, par
              exemple, un appel système  (tgkill(2),  kill(2),  sigqueue(3), etc.),  l'expiration
              d'un  minuteur  POSIX,  la modification d'état sur une file de messages POSIX où la
              fin d'une requête d'E/S asynchrone.

       si_code == SI_KERNEL (0x80)
              SIGTRAP a été envoyé par le noyau.

       si_code == SIGTRAP ou si_code == (SIGTRAP|0x80)
              C'est un arrêt-appel-système.

       Cependant, les arrêts-appel-système arrivent très souvent (deux fois par appel système) et
       réaliser PTRACE_GETSIGINFO pour chaque arrêt-appel-système pourrait être assez coûteux.

       Certaines  architectures  permettent de distinguer ces cas en examinant les registres. Par
       exemple, sur x86, rax == -ENOSYS en  arrêt-entrée-appel-système.  Puisque  SIGTRAP  (comme
       tout  autre  signal)  arrive  toujours  après  l'arrêt-sortie-appel-système  et que rax ne
       contient  à  ce   moment   presque   jamais   -ENOSYS,   le   SIGTRAP   ressemble   à   un
       « arrêt-appel-système  qui  n'est  pas un arrêt-entrée-appel-système » ; autrement dit, il
       ressemble à un « arrêt-sortie-appel-système perdu » et peut être détecté de  cette  façon.
       Une telle détection est néanmoins fragile, elle est donc a éviter.

       L'utilisation  de l'option PTRACE_O_TRACESYSGOOD est la méthode conseillée pour distinguer
       les arrêts-appel-système des  autres  sortes  d'arrêts-ptrace,  puisqu'il  est  fiable  et
       n'induit pas de perte de performances.

       Les  arrêt-entrée-appel-système  et arrêt-sortie-appel-système ne sont pas différentiables
       l'un de l'autre. L'observateur doit garder une trace de la suite d'arrêts-ptrace  afin  de
       ne  pas  mal interpréter un arrêt-entrée-appel-système comme un arrêt-sortie-appel-système
       ou vice versa. La règle est que l'arrêt-entrée-appel-système est  toujours  suivi  par  un
       arrêt-sortie-appel-système,  un  arrêt PTRACE_EVENT ou la mort de l'observé ; aucune autre
       sorte d'arrêt-ptrace ne peut arriver entre-deux.

       Si  suite  à  un  arrêt-entrée-appel-système,  l'observateur  utilise  une   commande   de
       redémarrage différente de PTRACE_SYSCALL, l'arrêt-sortie-appel-système n'est pas créé.

       PTRACE_GETSIGINFO sur les arrêts-appel-système renvoie SIGTRAP dans si_signo, avec si_code
       configuré à SIGTRAP ou (SIGTRAP | 0x80).

   Arrêts PTRACE_SINGLESTEP, PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP
       [Les précisions sur ces types d'arrêts sont encore à documenter.]

   Commandes ptrace d'information et de redémarrage
       La plupart des commandes ptrace (toutes sauf PTRACE_ATTACH, PTRACE_SEIZE,  PTRACE_TRACEME,
       PTRACE_INTERRUPT  et PTRACE_KILL) nécessitent que l'observé soit en arrêt-ptrace, sinon il
       échoue avec ESRCH.

       Quand l'observé est en arrêt-ptrace, l'observateur peut lire  et  écrire  les  donnés  sur
       l'observé  en  utilisant  les commandes d'information. Ces commandes laissent l'observé en
       état arrêté-ptrace :

           ptrace(PTRACE_PEEKTEXT/PEEKDATA/PEEKUSER, pid, addr, 0);
           ptrace(PTRACE_POKETEXT/POKEDATA/POKEUSER, pid, addr, long_val);
           ptrace(PTRACE_GETREGS/GETFPREGS, pid, 0, &struct);
           ptrace(PTRACE_SETREGS/SETFPREGS, pid, 0, &struct);
           ptrace(PTRACE_GETREGSET, pid, NT_foo, &iov);
           ptrace(PTRACE_SETREGSET, pid, NT_foo, &iov);
           ptrace(PTRACE_GETSIGINFO, pid, 0, &siginfo);
           ptrace(PTRACE_SETSIGINFO, pid, 0, &siginfo);
           ptrace(PTRACE_GETEVENTMSG, pid, 0, &long_var);
           ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_flags);

       Remarquez que certaines erreurs ne sont  pas  signalées.  Par  exemple,  la  configuration
       d'informations  de  signal (siginfo) pourrait être sans effet pour certains arrêts-ptrace,
       alors que l'appel pourrait-être réussi (en renvoyant 0 et sans définir errno) ; la demande
       de  PTRACE_GETEVENTMSG  pourrait  réussir  et  renvoyer une quelconque valeur aléatoire si
       l'arrêt-ptrace  actuel  n'est  pas  documenté  comme  renvoyant  un  message   d'événement
       significatif.

       L'appel

           ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_flags);

       ne  concerne  qu'un  observé.  Les  attributs  actuels  de  l'observé  sont remplacés. Les
       attributs sont hérités par les nouveaux observés créés et « attachés  automatiquement »  à
       l'aide d'options PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK ou PTRACE_O_TRACECLONE actives.

       Un  autre  groupe  de  commandes  peut  redémarrer l'observé arrêté ptrace. Ils sont de la
       forme :

           ptrace(cmd, pid, 0, sig);

       où  cmd est PTRACE_CONT, PTRACE_LISTEN, PTRACE_DETACH, PTRACE_SYSCALL,  PTRACE_SINGLESTEP,
       PTRACE_SYSEMU  ou PTRACE_SYSEMU_SINGLESTEP. Si l'observé est en arrêt-distribution-signal,
       sig est le signal à injecter (s'il est non nul). Sinon, sig pourrait être ignoré (lors  du
       redémarrage  d'un observé depuis un arrêt-ptrace différent d'un arrêt-distribution-signal,
       il est conseillé de toujours passer 0 à sig).

   Attachement et détachement
       Un thread peut être attaché à l'observateur en utilisant l'appel

           ptrace(PTRACE_ATTACH, pid, 0, 0);

       ou

           ptrace(PTRACE_SEIZE, pid, 0, PTRACE_O_flags);

       PTRACE_ATTACH envoie aussi SIGSTOP à ce thread. Si l'observateur  veut  que  SIGSTOP  soit
       sans  effet,  il doit le supprimer. Remarquez que si d'autres signaux sont envoyés en même
       temps à ce thread pendant l'attachement, l'observateur pourrait voir l'observé  entrer  en
       arrêt-distribution-signal  avec  d'autres  signaux  d'abord !  Ces signaux sont d'habitude
       réinjectés jusqu'à ce que SIGSTOP soit vu, puis  l'injection  SIGSTOP  est  supprimée.  Le
       bogue  de  conception  ici  est  qu'un attachement ptrace et un SIGSTOP distribués en même
       temps peuvent entrer en compétition et le SIGSTOP risque d'être perdu.

       Puisque l'attachement envoie SIGSTOP et que l'observateur le  supprime  normalement,  cela
       risque  de  forcer le retour d'un EINTR perdu de l'appel système en cours d'exécution dans
       l'observé, tel que c'est décrit dans la section Injection et suppression de signal.

       Depuis Linux 3.4, PTRACE_SEIZE peut être utilisé à la place de PTRACE_ATTACH. PTRACE_SEIZE
       n'arrête  pas  le  processus  attaché.  Si  vous  devez  l'arrêter après attachement (ou à
       n'importe quel autre moment) sans lui envoyer de signal  du  tout,  utilisez  la  commande
       PTRACE_INTERRUPT.

       La requête

           ptrace(PTRACE_TRACEME, 0, 0, 0);

       transforme  le thread appelant en observé. L'appel continue d'être exécuté (n'entre pas en
       arrêt-ptrace). PTRACE_TRACEME est habituellement suivi avec

           raise(SIGSTOP);

       et   permet   au    père    (qui    est    maintenant    l'observateur)    de    respecter
       l'arrêt-distribution-signal.

       Si  les options PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK ou PTRACE_O_TRACECLONE font effet,
       alors les fils respectivement créés par vfork(2) ou clone(2) avec l'attribut  CLONE_VFORK,
       vfork(2)  ou  clone(2) avec le signal de sortie configuré à SIGCHLD, et d'autres sortes de
       clone(2), sont automatiquement attachés au même observateur qui à suivi leur père. SIGSTOP
       est  distribué  aux  fils,  les  forçant  à entrer en arrêt-distribution-signal après être
       sortis de l'appel système qu'ils ont créé.

       Le détachement de l'observé est réalisé par :

           ptrace(PTRACE_DETACH, pid, 0, sig);

       PTRACE_DETACH est une  opération  de  redémarrage ;  par  conséquent  elle  nécessite  que
       l'observé  soit  en arrêt-ptrace. Si l'observé est en arrêt-distribution-signal, un signal
       peut être injecté. Sinon, le paramètre sig pourrait être silencieusement ignoré.

       Si l'observé est en cours d'exécution quand l'observateur veut le  détacher,  la  solution
       habituelle  est  d'envoyer SIGSTOP (en utilisant tgkill(2), pour s'assurer qu'il va au bon
       thread), d'attendre que l'observé s'arrête en arrêt-distribution-signal  pour  SIGSTOP  et
       ensuite de le détacher (en supprimant l'injection SIGSTOP). Un bogue de conception est que
       l'observé pourrait entrer dans d'autres arrêts-ptrace et avoir besoin d'être redémarré  et
       attendre  encore,  jusqu'à  ce  que  SIGSTOP soit vu. Encore une autre complication est de
       s'assurer que l'observé n'est pas déjà  arrêté-ptrace,  parce  qu'aucune  distribution  de
       signal n'arrive tant qu'il l'est — pas même SIGSTOP.

       Si  l'observateur  meurt,  tous  les observés sont automatiquement détachés et redémarrés,
       sauf s'il étaient en arrêt-groupe. Le gestion de redémarrage depuis un arrêt-groupe est en
       ce  moment  dysfonctionnelle,  mais  le comportement « prévu » est de laisser les observés
       arrêtés   et   d'attendre   un   SIGCONT.   Si   l'observé   est   redémarré   depuis   un
       arrêt-distribution-signal, le signal en attente est injecté.

   execve(2) sous ptrace
       Quand  un  thread  de  processus multithreadé appelle execve(2), le noyau détruit tous les
       autres threads du processus, et réinitialise l'identifiant de thread du thread  exécuté  à
       l'identifiant  de  groupe  de  threads  (PID)  (ou,  pour le présenter autrement, quand un
       processus multithreadé fait un execve(2), à la  fin  de  l'appel,  il  apparaît  comme  si
       l'execve(2)  s'était appliqué au leader de groupe de threads, quelque soit le thread qui a
       fait execve(2)). Cette  réinitialisation  de  l'identifiant  de  thread  semble  est  très
       déroutante pour les observateurs.

       *  Tous   les   autres   threads   s'arrêtent  en  arrêt  PTRACE_EVENT_EXIT,  si  l'option
          PTRACE_O_TRACEEXIT était activée. Alors tous les  autres  threads  sauf  le  leader  de
          groupe de threads signalent leur mort comme s'il s'étaient terminés par l'intermédiaire
          de _exit(2) avec un code de retour 0.

       *  L'observé en cours d'exécution modifie son identifiant de thread pendant qu'il est dans
          l'execve(2)  (rappelez-vous  que,  sous  ptrace,  le  « pid » renvoyé par waitpid(2) ou
          fourni dans les appels ptrace,  est  l'identifiant  de  thread  de  l'observé).  Ainsi,
          l'identifiant  de  thread  de  l'observé  est  réinitialisé  pour  être le même que son
          identifiant de processus (PID), qui est le même que l'identifiant de thread  du  leader
          de groupe de threads.

       *  Ensuite  un  arrêt  PTRACE_EVENT_EXEC  arrive,  si  l'option  PTRACE_O_TRACEEXEC  était
          activée.

       *  Si le leader de groupe de threads a signalé  son  arrêt  PTRACE_EVENT_EXIT  pendant  ce
          temps, le leader de thread mort à l'air de « revenir de nulle part » du point de vue de
          l'observateur (remarque : le leader de groupe de threads  ne  signale  pas  sa  mort  à
          l'aide de WIFEXITED(status) tant qu'au moins un autre thread est en vie. Cela enlève la
          possibilité à l'observateur de le voir mourir  puis  réapparaître).  Si  le  leader  de
          groupe de threads était encore en vie, cela pourrait être vu par l'observateur comme si
          le leader de groupe revenait d'un autre appel système que celui dans  lequel  il  était
          entré, ou même « revenait d'un appel système même s'il n'y avait pas d'appel système ».
          Si le leader de groupe de threads n'était pas  suivi  (ou  était  suivi  par  un  autre
          observateur),  alors pendant execve(2) il apparaîtra comme s'il était devenu un observé
          de l'observateur de l'observé en cours d'exécution.

       Tous les effets précédents sont des artifices de la modification d'identifiant  de  thread
       de l'observé.

       L'option  PTRACE_O_TRACEEXEC  est  l'outil  conseillé  pour  s'occuper de cette situation.
       D'abord, elle active l'arrêt PTRACE_EVENT_EXEC, qui arrive avant  le  retour  d'execve(2).
       Dans  cet  arrêt,  l'observateur  peut utiliser PTRACE_GETEVENTMSG pour récupérer l'ancien
       identifiant de thread de l'observé (cette fonctionnalité a été introduite avec Linux 3.0).
       Ensuite,  l'option  PTRACE_O_TRACEEXEC  désactive  la  création  obsolète  de SIGTRAP dans
       execve(2).

       Quand l'observé reçoit une notification d'arrêt PTRACE_EVENT_EXEC,  il  est  garanti  qu'à
       part  cet observé et le leader de groupe de threads, aucun autre thread du processus n'est
       en vie.

       Lors de la réception d'une notification d'arrêt PTRACE_EVENT_EXEC,  l'observateur  devrait
       nettoyer  toutes  ses structures de données internes décrivant les threads de ce processus
       et ne garder qu'une seule structure de données — celle  qui  décrit  l'unique  observé  en
       cours d'exécution, avec

           identifiant de thread == identifiant de groupe de threads == identifiant de processus.

       Par exemple, soient deux threads qui appellent execve(2) en même temps :

       *** arrêt-entrée-appel-système obtenu dans le thread 1 : **
       PID1 execve("/bin/truc", "truc" <pas terminé…>
       *** PTRACE_SYSCALL émis pour le thread 1 **
       *** arrêt-entrée-appel-système obtenu dans le thread 2 : **
       PID2 execve("/bin/bidule", "bidule" <pas terminé…>
       *** PTRACE_SYSCALL émis pour le thread 2 **
       *** PTRACE_EVENT_EXEC obtenu pour PID0, PTRACE_SYSCALL émis **
       *** arrêt-sortie-appel-système obtenu pour PID0 : **
       PID0 <… retour d'execve> )             = 0

       Si l'option PTRACE_O_TRACEEXEC n'est pas effective pour l'observé en cours d'exécution, le
       noyau distribue un SIGTRAP supplémentaire à l'observé après le retour  d'execve(2).  C'est
       un  signal  normal  (similaire  à  celui qui peut être créé par kill -TRAP), pas une sorte
       spéciale d'arrêt-ptrace. L'utilisation de PTRACE_GETSIGINFO pour ce signal renvoie si_code
       configuré  à  0  (SI_USER).  Ce  signal  pourrait  être bloqué par un masque de signal, et
       pourrait ainsi être distribué (bien) plus tard.

       Normalement, l'observé (par exemple strace(1)) ne voudrait pas montrer ce  signal  SIGTRAP
       post-execve  supplémentaire  à  l'utilisateur,  et  voudrait  supprimer  sa distribution à
       l'observé (si SIGTRAP  est  configuré  à  SIG_DFL,  s'est  un  signal  tueur).  Cependant,
       déterminer  quel est le SIGTRAP à supprimer n'est pas simple. La configuration de l'option
       PTRACE_O_TRACEEXEC  et  par  conséquent  la  suppression  du  SIGTRAP  supplémentaire  est
       l'approche conseillée.

   Vrai père
       L'interface  de programmation de ptrace utilise (parfois mal) la norme UNIX de signalement
       de père ou fils par l'intermédiaire de waitpid(2). Cela a régulièrement forcé le vrai père
       du  processus  à arrêter de recevoir plusieurs sortes de notifications de waitpid(2) quand
       le processus fils est suivi par un autre processus.

       Nombreux bogues de ce type ont été  corrigés,  mais  il  en  reste  encore  beaucoup  dans
       Linux 2.6.38. Consultez la section BOGUES ci dessous.

       Depuis Linux 2.6.38, ce qui suit est censé fonctionner correctement :

       *  l'exécution  ou  la mort par signal sont d'abord signalées à l'observateur, puis, quand
          l'observateur consomme le résultat de waitpid(2), au vrai père (au vrai père  seulement
          quand  l'intégralité du processus multithreadé se termine). Si l'observateur et le vrai
          père sont le même processus, le signalement n'est envoyé qu'une fois.

VALEUR RENVOYÉE

       En cas de succès, la requête PTRACE_PEEK* renvoie les données  demandées  (mais  consultez
       les NOTES), alors que les autres requêtes renvoient zéro.

       ptrace()  renvoie  -1  en cas d'échec en remplissant errno avec le code d'erreur. Comme la
       valeur renvoyée par une requête PTRACE_PEEK* peut légitimement être  -1,  l'appelant  doit
       effacer  errno  avant  l'appel,  et  ensuite  le  vérifier pour savoir si une erreur s'est
       produite.

ERREURS

       EBUSY  (i386 seulement) Une erreur est survenue lors de l'allocation ou de  la  libération
              d'un registre de débogage.

       EFAULT Tentative  de  lire ou écrire dans une zone mémoire non valable de l'observateur ou
              de l'observé, probablement parce que la zone n'était pas  projetée  ou  accessible.
              Malheureusement  sous  Linux, certaines variantes de cette erreur déclencheront EIO
              ou EFAULT plus ou moins arbitrairement.

       EINVAL Tentative d'utiliser une option non valable.

       EIO    La requête request n'est pas valable ou une tentative de lecture ou d'écriture dans
              une  zone  non  valable  de  mémoire de l'observateur ou de l'observé a eu lieu. Un
              problème d'alignement a aussi  pu  survenir  sur  une  frontière  de  mot,  ou  une
              tentative de redémarrage en envoyant un signal non valable.

       EPERM  Le  processus  indiqué  ne  peut  pas  être suivi. Cela peut être dû à un manque de
              privilège  de  l'observateur  (la  capacité  nécessaire  est  CAP_SYS_PTRACE).  Les
              processus  non  privilégiés  ne  peuvent  pas  suivre les processus auxquels ils ne
              peuvent envoyer de signal, ou ceux qui s'exécutent Set-UID/Set-GID.  En  outre,  le
              processus  visé  peut être déjà suivi, ou (sur les noyaux antérieurs à 2.6.26) être
              init(8) (le processus numéro 1).

       ESRCH  Le processus indiqué n'existe pas, ou n'est pas suivi par l'appelant, ou n'est  pas
              arrêté (pour les requêtes qui ont besoin d'un observé arrêté).

CONFORMITÉ

       SVr4, BSD 4.3.

NOTES

       Bien  que  les  arguments de ptrace() soient interprétés comme dans le prototype donné, la
       bibliothèque glibc déclare ptrace comme une fonction variadique où seul l'argument request
       est corrigé. Il vaut mieux toujours fournir quatre arguments, même si l'opération demandée
       ne les utilise pas, en  configurant  les  arguments  non  utilisés  ou  ignorés  à  0L  ou
       (void *) 0.

       L'interface  de  programmation  de  l'appel  système  est  différente  pour  les  requêtes
       PTRACE_PEEKTEXT,  PTRACE_PEEKDATA  et  PTRACE_PEEKUSER :  elles  stockent  le  résultat  à
       l’adresse  indiquée par le paramètre data, et la valeur de retour est l’attribut d’erreur.
       La fonction glibc encapsulant cet appel fournit une interface détaillée  dans  la  section
       DESCRIPTION ci-dessus, et le résultat qu'elle renvoie est le résultat de l'appel système.

       Dans  les  noyaux  antérieurs  à  2.6.26, init(8), le processus numéro 1, ne peut pas être
       suivi.

       La disposition du contenu  de  la  mémoire  et  de  la  zone  USER  dépendent  du  système
       d'exploitation  et  de l'architecture. Le décalage fourni et les données renvoyées peuvent
       ne pas correspondre entièrement avec la définition d'une structure struct user.

       La taille d'un mot (« word ») est déterminée par la version du système d'exploitation (par
       exemple 32 bits pour Linux 32 bits).

       Cette page documente le fonctionnement actuel de ptrace() sous Linux. Celui-ci peut varier
       sensiblement sur d'autres types d'UNIX. De toute façon, l'utilisation de  ptrace()  dépend
       fortement de l'architecture et du système d'exploitation.

BOGUES

       Sur  les  machines ayant des en-têtes du noyau 2.6, PTRACE_SETOPTIONS est déclaré avec une
       valeur différente de celle du noyau 2.4. De ce fait, les applications compilées  avec  des
       en-têtes  du  noyau 2.6  ne peuvent pas s'exécuter sous des noyaux 2.4. Il est possible de
       contourner cette difficulté en redéfinissant PTRACE_SETOPTIONS à PTRACE_OLDSETOPTIONS,  si
       cette dernière constante est définie.

       Les  notifications  d'arrêt-groupe  sont  envoyées à l'observateur, mais pas au vrai père.
       C'était encore vrai en 2.6.38.6.

       Si un leader de groupe de threads est suivi et  existe  en  appelant  _exit(2),  un  arrêt
       PTRACE_EVENT_EXIT  lui  arrivera  (si réclamé), mais la notification WIFEXITED suivante ne
       sera pas distribuée avant la fin de tous les autres threads. Comme expliqué  précédemment,
       si un des autres threads appelle execve(2), la mort du leader de groupe de threads ne sera
       jamais signalée. Si le thread exécuté n'est pas suivi par cet  observateur,  l'observé  ne
       saura  jamais qu'execve(2) est arrivé. Un contournement possible est de PTRACE_DETACHer le
       leader de groupe de threads au lieu de le redémarrer dans ce cas. C'était encore  vrai  en
       2.6.38.6.

       Un signal SIGKILL pourrait encore provoquer un arrêt PTRACE_EVENT_EXIT avant une véritable
       mort du signal. Cela pourrait évoluer à l'avenir. SIGKILL est supposé  tuer  immédiatement
       les tâches même sous ptrace. C'était encore vrai en 2.6.38.6.

       Certains appels système renvoient EINTR si un signal a été envoyé à l'observé, mais que la
       distribution  a  été  supprimée  par  l'observateur  (c'est  une  opération  tout  à  fait
       caractéristique :   elle  est  normalement  réalisée  par  les  débogueurs  sur  tous  les
       attachements, afin de ne pas introduire de SIGSTOP défectueux). Depuis  Linux  3.2.9,  les
       appels  système  suivants  sont  concernés  (cette  liste  est  sans  doute  incomplète) :
       epoll_wait(2) et  read(2)  depuis  un  descripteur  de  fichier  inotify(7).  Le  symptôme
       classique de ce bogue est qu'en attachant à un processus quiescent avec la commande

           strace -p <ID-processus>

       alors, au lieu de la ligne de sortie habituelle attendue comme

           restart_syscall(<... retour de l'appel interrompu ...>_

       ou

           select(6, [5], NULL, [5], NULL_

       (« _ » indique la position du curseur), plusieurs lignes sont affichées. Par exemple :

           clock_gettime(CLOCK_MONOTONIC, {15370, 690928118}) = 0
           epoll_wait(4,_

       Ce  qui  n'est  pas visible ici est que le processus a été bloqué dans epoll_wait(2) avant
       que strace(1) ne s'y soit attaché. L'attachement a  forcé  epoll_wait(2)  à  revenir  dans
       l'espace utilisateur avec l'erreur EINTR. Dans ce cas particulier, le programme a réagit à
       EINTR en vérifiant l'heure actuelle et en exécutant encore epoll_wait(2)  (les  programmes
       qui  ne  s'attendent  pas à de telles erreurs EINTR « perdue » risquent de se comporter de
       façon inattendue sur une attache strace(1)).

VOIR AUSSI

       gdb(1), strace(1),  clone(2),  execve(2),  fork(2),  gettid(2),  sigaction(2),  tgkill(2),
       vfork(2), waitpid(2), exec(3), capabilities(7), signal(7)

COLOPHON

       Cette  page  fait partie de la publication 3.65 du projet man-pages Linux. Une description
       du projet et des  instructions  pour  signaler  des  anomalies  peuvent  être  trouvées  à
       l'adresse http://www.kernel.org/doc/man-pages/.

TRADUCTION

       Depuis    2010,    cette   traduction   est   maintenue   à   l'aide   de   l'outil   po4a
       <http://po4a.alioth.debian.org/> par l'équipe de traduction francophone au sein du  projet
       perkamon <http://perkamon.alioth.debian.org/>.

       Christophe    Blaess    <http://www.blaess.fr/christophe/>   (1996-2003),   Alain   Portal
       <http://manpagesfr.free.fr/>  (2003-2006).  Julien  Cristau  et  l'équipe  francophone  de
       traduction de Debian (2006-2009).

       Veuillez     signaler     toute     erreur     de     traduction     en     écrivant     à
       <debian-l10n-french@lists.debian.org>  ou  par  un  rapport  de  bogue   sur   le   paquet
       manpages-fr.

       Vous  pouvez  toujours  avoir  accès  à la version anglaise de ce document en utilisant la
       commande « man -L C <section> <page_de_man> ».