GDB / DDD: отладка разделяемой библиотеки с помощью многопроцессорного приложения C / C ++

0

Я пытаюсь отлаживать серверное приложение, но я сталкиваюсь с некоторыми трудностями, ломая, где мне нужно. Приложение разбито на две части:

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

Как добавленный самородок радости, рабочий обрабатывает "респаун" (т.е. Выход и новый рабочий процесс порождается), поэтому PID детей периодически меняются. -_-"

В основном мне нужно отлаживать службу, вызываемую в общей библиотеке, но я не знаю, к какому процессу присоединяться досрочно, так как они захватывают запросы ad-hoc. Присоединение к основному процессу и установка точки останова пока не работало.

Есть ли способ отлаживать этот код общей библиотеки без предварительного прикрепления к процессу? В принципе, я бы хотел отладить первый процесс, который вызвал эту функцию.

В настоящее время я, вероятно, попытаюсь ограничить число рабочих процессов до 1 без респауна, но было бы хорошо знать, как обрабатывать такой сценарий в будущем, особенно если я хочу убедиться, что это все еще работает в конфигурации "release".

Я работаю на платформе Linux, пытаясь отладить это с помощью DDD и GDB.

Изменение: Чтобы проиллюстрировать то, что я пытаюсь выполнить, позвольте мне представить краткое доказательство концепции.

#include <iostream>
#include <stdlib.h>
#include <unistd.h>

using namespace std;

int important_function( const int child_id )
{
    cout << "IMPORTANT(" << child_id << ")" << endl;
}

void child_task( const int child_id )
{
    const int delay = 10 - child_id;
    cout << "Child " << child_id << " started. Waiting " << delay << " seconds..." << endl;
    sleep(delay);
    important_function(child_id);
    exit(0);
}

int main( void )
{
    const int children = 10;
    for (int i = 0; i < 10; ++i)
    {
        pid_t pid = fork();
        if (pid < 0) cout << "Fork " << i << "failed." << endl;
        else if (pid == 0) child_task(i);
    }

    sleep(10);
    return 0;
}

Эта программа разветкит 10 процессов, которые будут спать 10 секунд за секунду до вызова функции important_function, функции, в которой я хочу отлаживать в первом вызывающем дочернем процессе (который должен быть здесь последним для fork).

Установка режима follow-fork для ребенка позволит мне перейти к первому ребёнку, который не является тем, что я ищу. Я ищу первого ребенка, который называет важную функцию.

Установка отключаемого на fork off не помогает, потому что он останавливает родительский процесс до тех пор, пока дочерний процесс не разблокирует выходы, прежде чем продолжить разветвление других процессов (по одному, после выхода последнего).

В реальном сценарии важно также, чтобы я мог подключаться к уже запущенному серверному приложению, которое уже порождало потоки, и останавливать первый из тех, кто вызывает эту функцию.

Я не уверен, что это возможно, так как я не видел на нем много документации. В основном я хочу отлаживать первое приложение для вызова этой строки кода, независимо от того, из какого процесса он исходит. (Хотя это только мои процессы приложений, которые вызовут код, похоже, что моя проблема может быть более общей: привязка к первому процессу, который вызывает код, независимо от его происхождения).

Теги:
multiprocessing
gdb

1 ответ

0
Лучший ответ

Вы можете установить точку останова в fork(), а затем выдать команды "продолжить", пока основной процесс следующего шага не будет создан дочерний процесс, который вы хотите отлаживать. В этот момент установите точку останова в функции, которую вы хотите отлаживать, а затем введите команду "set child-fork-mode child" в gdb. Когда вы продолжаете, gdb должен подключить вас к дочернему процессу в функции, где находится точка останова.

Если вы выпустите команду "set detach-on-fork off", gdb продолжит отладку дочерних процессов. Процесс, который попадает в точку останова в библиотеке, должен останавливаться, когда он достигает этой точки останова. Проблема заключается в том, что при отключении отключаемой функции gdb останавливает все дочерние процессы, которые разворачиваются при их запуске. Я не знаю, как сказать, чтобы продолжать выполнять эти процессы после форкирования.

Для решения этой проблемы я бы хотел написать сценарий gdb для переключения на каждый процесс и выпустить команду continue. Процесс, который обращается к функции с точкой останова, должен останавливаться.

Один из коллег предложил другое решение проблемы получения каждого ребенка. Вы можете оставить "detach-on-fork" включенным, вставить инструкцию печати в каждую точку ввода дочернего процесса, которая выводит свой идентификатор процесса, а затем дать ей инструкцию, в которой говорится, что она ждет изменения переменной, например:

{
    volatile int foo = 1;
    printf("execute \"gdb -p %u\" in a new terminal\n", (unsigned)getpid());
    printf("once GDB is loaded, give it the following commands:\n");
    printf("    set variable foo = 0\n");
    printf("    c\n");
    while (foo == 1) __asm__ __volatile__ ("":::"memory");
}

Затем запустите gdb, запустите основной процесс и подайте вывод в файл. С помощью сценария bash вы можете читать идентификаторы процессов для детей, запускать несколько экземпляров gdb, присоединять каждый экземпляр к одному из разных дочерних процессов и сигнализировать каждому, чтобы продолжить, очистив переменную "foo".

  • 0
    Проблема в том, что я не знаю, какой ребенок примет и обработает запрос к серверу. Это не сделано детерминистическим способом; скорее, процессы ждут входящего соединения и затем пытаются принять его, поэтому то, кто получает его от процессов ожидания, зависит от того, кому посчастливилось запустить его, когда поступит запрос.
  • 0
    Пожалуйста, смотрите обновление к моему ответу.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню