2012-11-14 10 views
5

Ich möchte ptrace verwenden, um zu überprüfen, welches System ein von meinem Programm erzeugtes Programm aufruft. Ich begann von this tutorial, wie es in einer Antwort auf meine previous question erklärt wurde. Ich den Code modifiziert, indem sie auf die Plattform anzupassen ich verwende (SLES 11 64-Bit), und zusammen den folgenden Testcode, der erzeugte Prozess jedes System aufrufen druckt macht:Verwenden von ptrace aus Multithread-Anwendungen

#include <sys/ptrace.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <sys/reg.h> 
#include <sys/syscall.h> /* For SYS_write etc */ 

pid_t child; 

void run() 
{ 
    long orig_eax; 
    int status; 

    while(1) { 
      int pid = wait(&status); 
      if (pid == -1) { 
       perror("wait"); 
       kill(child, SIGKILL); 
       return; 
      } 
      printf("Got event from %d.\n", pid); 
      if(WIFEXITED(status)) 
       break; 
      orig_eax = ptrace(PTRACE_PEEKUSER, 
        pid, 8 * ORIG_RAX, NULL); 
      if (orig_eax == -1) { 
       perror("ptrace"); 
       kill(child, SIGKILL); 
       return; 
      } else { 
       printf("Syscall %ld called.\n", orig_eax); 
      } 
      ptrace(PTRACE_SYSCALL, 
        pid, NULL, NULL); 
    } 
} 

int main(int /*argc*/, char* argv[]) 
{ 

    child = fork(); 
    if(child == 0) { 
     ptrace(PTRACE_TRACEME, 0, NULL, NULL); 
     execl(argv[1], argv[1], NULL); 
    } 
    else { 
     printf("Child process id = %d.\n", child); 
     run(); 

    } 
    return 0; 
} 

Es funktioniert ziemlich gut : Es druckt die ID der Systemaufrufe, die vom Programm gemacht werden (tatsächlich druckt es jedes zweimal, einmal beim Eintritt und einmal beim Verlassen, aber das ist jetzt egal). Allerdings muss mein Programm andere Dinge tun, als die Systemaufrufe zu überprüfen, also entschied ich, die Überprüfung in einen separaten Thread zu verschieben (ich bin wohler mit C++ als C, also habe ich es C++ gemacht, aber ich glaube nicht, dass das wichtig ist). Natürlich starte ich in diesem Thest Programm nur den Thread und schließe mich dann an.

#include <sys/ptrace.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <sys/reg.h> 
#include <sys/syscall.h> /* For SYS_write etc */ 

#include <boost/thread.hpp> 


pid_t child; 

void run() 
{ 
    long orig_eax; 
    int status; 

    while(1) { 
      int pid = wait(&status); 
      if (pid == -1) { 
       perror("wait"); 
       kill(child, SIGKILL); 
       return; 
      } 
      printf("Got event from %d.\n", pid); 
      if(WIFEXITED(status)) 
       break; 
      orig_eax = ptrace(PTRACE_PEEKUSER, 
        pid, 8 * ORIG_RAX, NULL); 
      if (orig_eax == -1) { 
       perror("ptrace"); 
       kill(child, SIGKILL); 
       return; 
      } else { 
       printf("Syscall %ld called.\n", orig_eax); 
      } 
      ptrace(PTRACE_SYSCALL, 
        pid, NULL, NULL); 
    } 
} 

int main(int /*argc*/, char* argv[]) 
{ 

    child = fork(); 
    if(child == 0) { 
     ptrace(PTRACE_TRACEME, 0, NULL, NULL); 
     execl(argv[1], argv[1], NULL); 
    } 
    else { 
     printf("Child process id = %d.\n", child); 
     boost::thread t(run); 
     t.join(); 
    } 
    return 0; 
} 

Dieses Mal habe ich eine Fehlermeldung erhalten:

Child process id = 24682. 
Got event from 24682. 
ptrace: No such process 

Warum ist das? Ich habe versucht, nach einer Antwort zu suchen, fand aber nichts dergleichen. Ich habe festgestellt, dass ptrace keine vom Kindprozess gestarteten Threads zurückverfolgen kann, aber das ist eine andere Sache, mit der später umgegangen werden muss. Ist das überhaupt möglich, um den Kindprozess von einem anderen Therad aus zu überprüfen?

Die andere seltsame Sache ist, dass ich in meiner realen Anwendung im Grunde dasselbe (aber aus einem viel komplizierteren Kontext: Klassen, Mutexe usw.), und ich bekomme eine andere Art von Fehler. Anstatt ptrace mit einem Fehler zurückzukehren, kehrt wait nicht einmal für Systemaufrufe auf dem untergeordneten Prozess zurück (und der untergeordnete Prozess wird nicht einmal beendet). Auf der anderen Seite funktioniert wait wie erwartet, wenn der untergeordnete Prozess beendet wird.

Antwort

1

Soweit ich das beurteilen kann, ptrace ermöglicht nur einen Tracer pro Prozess. Dies bedeutet, dass beim Versuch, eine Verbindung herzustellen, die Sie mit PTRACE_ATTACH erzwingen können, ein Fehler angezeigt wird, der besagt, dass ptrace nicht an den angegebenen Prozess angehängt werden konnte.

So erscheint Ihr Fehler, weil Ihr Thread nicht an den untergeordneten Prozess angeschlossen ist, und auf diese Weise, wenn Sie versuchen, ptrace es, schlägt es fehl und sendet einen -ESRCH Code.

Darüber hinaus können Sie sehen this post here, könnte es einige andere Fragen beantworten, die Sie abgesehen von diesem möglicherweise haben.

+0

Mit einem eigenen Thread zu meinem Prozess geholfen. – petersohn

Verwandte Themen