GDB: отладка дочернего процесса после множества fork () - PullRequest
4 голосов
/ 30 сентября 2011

Я отлаживаю программу, которая повторяет типичную процедуру использования fork(), когда дочерний процесс выполняет некоторую делегированную задачу, так как родительский вызывает waitpid(), чтобы дождаться завершения дочернего процесса, а затем продолжает,Например:

while (!finished) {
    pid_t p = fork();
    if (p < 0) {
        perror("fork");
        exit(EXIT_FAILURE);
    }
    else if (p == 0) {
        /* Do something. For example: */
        if (/* some (rare) condition */) 
            raise(SIGSEGV);
        exit(EXIT_SUCCESS);
    }
    else {
        int status;
        pid_t w = waitpid(p, &status, 0);
        if (w < 0) {
            perror("waitpid");
            exit(EXIT_FAILURE);
        }
        /* Do something. */
    }
}

Я бы хотел запустить программу внутри GDB и отладить дочерний процесс, который получает сигнал, независимо от того, сколько других дочерних процессов успешно завершилось и исчезло до него .

Конечно, мне нужен set follow-fork-mode child, потому что в противном случае GDB не будет смотреть на дочерние процессы.Но это само по себе отсоединит родителя, приведет GDB к первому дочернему элементу и завершит отладку при его выходе.

Поэтому мне также нужно set detach-on-fork off, чтобы предотвратить отсоединение родителя.Однако это приводит к тому, что GDB останавливается и выдает подсказку с приостановкой работы родителя при выходе из первого ребенка.Я мог бы использовать inferior, чтобы выбрать родителя и выдать continue, но Мне нужно сделать это для каждого ребенка .Если 1000-й ребенок - это тот, кто получает сигнал и на который я хочу посмотреть, мне нужно повторить этот процесс 999 раз.

Поэтому мне интересно, есть ли способ, в некотором роде, сделатьэто автоматически, и пусть GDB следит за тем, что будет исполнять процессор, например, parent → child1 → parent → child2 →…, не останавливаясь и не подсказывая мне, и останавливается у первого childN, который получает сигнал.

1 Ответ

3 голосов
/ 30 сентября 2011

Если сигнал, который вы хотите отладить, это SIGSEGV (или один из других сигналов, вызывающих дамп ядра программы), самое простое решение может состоять в том, чтобы просто позволить дочернему дампу ядра и выполнить посмертное отладки.

В противном случае вы можете захотеть поймать сигнал, напечатать сообщение по линии child 23435 caught signal 2; execute gdb /proc/23435 23435, а затем приостановить действия ребенка, например,

while(1) sleep(1);
...