почему PTRACE_CONT отправляет сигнал SIGPROF удаленному процессу? - PullRequest
0 голосов
/ 03 апреля 2020

Я использую libunwind-ptrace для мониторинга стека вызовов удаленного процесса.

Необходимо периодически получать имя текущего вызова функции, поэтому после подключения к удаленному процессу с помощью ptrace (который будет SIGSTOP удаленный процесс), сначала я пишу al oop, который выбирает состояния с фиксированным интервалом, затем продолжаю удаленный процесс с PTRACE_CONT (вызов любого сигнала, включая сбор информации, например, GETREGS, отправленный ptrace, остановит удаленный процесс) .

Однако я обнаружил, что таймер работает не так, как я ожидал. Это замедляет выполнение удаленного процесса, а не просто изменяет частоту дискретизации, не влияя на выполнение удаленной программы. Я полагаю, что PTRACE_CONT не продолжает процесс немедленно.

Затем я закомментирую таймер сна и добавлю waitpid logi c, чтобы поймать сигнал, отправленный PTRACE_CONT, что удивительно, это дает мне результат остановленный сигнал с номером 27 , который является SIGPROF сигналом.

Коды перечислены ниже:

#include "libunwind.h"
#include "libunwind-x86_64.h"
#include "libunwind-ptrace.h"

#include <stdio.h>      
#include <stdlib.h>
#include <string.h>

#include <time.h>
#include <sys/ptrace.h>
#include <sys/wait.h>

static unw_addr_space_t as;
static struct UPT_info *ui;

struct timespec t = { .tv_sec = 0, .tv_nsec = 1000000 };

void do_backtrace(pid_t pid) {

    ui = _UPT_create(pid);
    if (!ui) {
        printf("_UPT_create failed\n");
    }

    unw_cursor_t c;

    int rc = unw_init_remote(&c, as, ui);
    if (rc != 0) {
        printf("unw_init_remote failed with ret value:%d\n", rc);
        _UPT_destroy(ui);
        return;
    }

    unw_word_t  offset, pc;
    char        fname[64];

    fname[0] = '\0';
    (void) unw_get_proc_name(&c, fname, sizeof(fname), &offset);

    _UPT_destroy(ui);
}


int main(int argc, char **argv) {

    as = unw_create_addr_space (&_UPT_accessors, 0);
    if (!as)
        printf("unw_create_addr_space() failed\n");

    if (argc != 2 && argc != 3) { 
        printf("usage: ./a.out pid [ns]\n");
        return -1;
    }

    pid_t target_pid = atoi(argv[1]);
    if (argc == 3) {
        t.tv_nsec = atol(argv[2]);  
        printf("sample at %ld ns\n", t.tv_nsec);
    }

    if (ptrace(PTRACE_ATTACH, target_pid, 0, 0) != 0) {
        printf("ptrace attach %d failed\n", target_pid);
        return -1;
    }

    if (ptrace(PTRACE_CONT, target_pid, 0, 0) != 0) {
        printf("ptrace continue %d failed\n", target_pid);
        return -1;
    }

    int status;
    while (1) {
        waitpid(target_pid, &status, __WALL);
        if (WIFEXITED (status)) {
            printf("target process exited.\n");
            break;
        }
        else if (WIFCONTINUED(status)) {
            printf("continued: %d\n", status);
        }
        else if (WIFSIGNALED(status)) {
            printf("terminated by: %d\n", WTERMSIG(status));
        }
        else if (WIFSTOPPED(status)) {
            printf("stopped by: %d\n", WSTOPSIG(status));
        }
        else {
            printf("signal: %d\n", status);
        }

        //nanosleep(&t, NULL);
        do_backtrace(target_pid);

        if (ptrace(PTRACE_CONT, target_pid, 0, SIGCONT) != 0) {
            printf("ptrace continue %d failed\n", target_pid);
            return -1;
        }
    }

    printf("ptrace detached: %ld\n", ptrace(PTRACE_DETACH, target_pid, 0, 0));

    return 0;
}

Любой может сказать мне почему таймер не работает, и механизм ptrace для остановки и возобновления удаленного процесса?

Большое спасибо.

...