Wie verwende ich PTRACE, um eine konsistente Ansicht mehrerer Threads zu erhalten?
Während ich arbeiteteauf diese FrageIch bin auf eine mögliche Idee gestoßen, die benutztptrace
, aber ich kann nicht richtig verstehen, wieptrace
interagiert mit Threads.
Angenommen, ich habe einen bestimmten Multithread-Hauptprozess und möchte ihn an einen bestimmten Thread anhängen (möglicherweise von einem verzweigten Kind).
Kann ich an einen bestimmten Thread anhängen? (Die Handbücher gehen in dieser Frage auseinander.)
Wenn ja, bedeutet das, dass beim Einzelschritt nur die Anweisungen dieses einen Threads durchlaufen werden? Stoppt es alle Threads des Prozesses?
Wenn ja, bleiben alle anderen Threads angehalten, während ich anrufePTRACE_SYSCALL
oderPTRACE_SINGLESTEP
oder tunalles Fäden weiter? Gibt es eine Möglichkeit, nur in einem einzelnen Thread vorwärtszugehen, aber sicherzustellen, dass die anderen Threads angehalten bleiben?
Grundsätzlich möchte ich das ursprüngliche Programm synchronisieren, indem ich alle Threads zum Stoppen zwinge und dann nur einen kleinen Satz von Single-Thread-Anweisungen durch schrittweises Ausführen des einen verfolgten Threads ausführen möchte.
Meine bisherigen persönlichen Versuche sehen ungefähr so aus:
pid_t target = syscall(SYS_gettid); // get the calling thread's ID
pid_t pid = fork();
if (pid > 0)
{
waitpid(pid, NULL, 0); // synchronise main process
important_instruction();
}
else if (pid == 0)
{
ptrace(target, PTRACE_ATTACH, NULL, NULL); // does this work?
// cancel parent's "waitpid" call, e.g. with a signal
// single-step to execute "important_instruction()" above
ptrace(target, PTRACE_DETACH, NULL, NULL); // parent's threads resume?
_Exit(0);
}
Ich bin mir jedoch nicht sicher und kann keine geeigneten Referenzen finden, dass dies gleichzeitig korrekt ist und dassimportant_instruction()
wird garantiert nur ausgeführt, wenn alle anderen Threads gestoppt sind. Ich verstehe auch, dass es Rennbedingungen geben kann, wenn die Eltern Signale von einer anderen Stelle empfangen, und ich habe gehört, dass ich diese verwenden solltePTRACE_SEIZE
stattdessen, aber das scheint nicht überall zu existieren.
Jede Klarstellung oder Hinweise wäre sehr dankbar!