Provided by: manpages-fr-dev_3.57d1p1-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é).

       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é).

       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

       Pour  les  requêtes  PTRACE_PEEK*,  ptrace()  renvoie  la valeur réclamée et zéro pour les
       autres requêtes. (Sous Linux, c’est fait dans la fonction libc autour de  l’appel  système
       ptrace. Au niveau de l’appel système, les requêtes PTRACE_PEEK* ont une autre interface de
       programmation : elles stockent le résultat à l’adresse indiquée par le paramètre data,  et
       la valeur de retour est l’attribut d’erreur.)

       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.

       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.57 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> ».