В любом случае можно ли разрешить одному потоку приложения продолжить работу в точке останова в GDB? - PullRequest
4 голосов
/ 09 марта 2011

При отладке приложения с использованием библиотеки времени выполнения Apache Zookeeper C я сталкиваюсь с проблемами при установке точек останова со стандартным режимом остановки в GDB.Если поток Zookeeper не может быть запущен, сервер прервет сеанс и, таким образом, удалит все временные узлы, которые вы, возможно, создали.Используя нон-стоп режим, я могу предотвратить это, но я теряю удобство в том, что могу исследовать состояние любого не-Zookeeper потока.

Есть ли способ в GDB указать, что один (или более) поток будет продолжать работать в приложении при достижении точки останова, но другие прекратят работу?Таким образом, я могу проверить состояние потоков, которые мне нужны, и игнорировать состояние тех, которые я хочу запустить в фоновом режиме.

Редактировать: По сути, это дубликат , не останавливая все потоки в GDB * 1006.*.Решение использовать фоновые команды в режиме без остановки по существу решает мою проблему, поскольку я могу остановить потоки и перезапустить их асинхронно, когда захочу, поэтому, возможно, нам следует закрыть эту.

Ответы [ 3 ]

0 голосов
/ 11 марта 2011

Вы можете установить специфичные для потока точки останова:

(gdb) help break
Set breakpoint at specified line or function.
break [LOCATION] [thread THREADNUM] [if CONDITION]
LOCATION may be a line number, function name, or "*" and an address.
If a line number is specified, break at start of code for that line.
If a function is specified, break at start of code for that function.
If an address is specified, break at that exact address.
With no LOCATION, uses current execution address of the selected
stack frame.  This is useful for breaking on return to a stack frame.

THREADNUM is the number from "info threads".
CONDITION is a boolean expression.
0 голосов
/ 23 марта 2011

С Zookeeper выясняется, что вы можете выполнить хак, чтобы продолжить сеанс, прерванный в GDB. Этот хак использует несколько свойств Zookeeper и gdb:

  • Вы можете иметь несколько клиентов Zookeeper с одинаковым идентификатором сессии
  • GDB не останавливает дочерние процессы в родительских точках останова
  • Вы можете игнорировать сигналы GDB в дочернем процессе, не затрагивая родительский

Исходя из этого, решение порождает дочерний процесс, который подключается к Zookeeper с тем же идентификатором клиента, что и родительский, и больше ничего не делает. Однако клиенты Zookeeper имеют понятие перемещения сеансов, когда клиент очень часто переключается с тем сервером, к которому он подключен. Если у вас есть два клиента с одинаковым идентификатором сеанса, один из них может переместиться, оставив другого подключенным к серверу, который не держит их сеанс. Чтобы предотвратить это, дочерний элемент должен подключаться только к серверу, к которому в данный момент подключен родительский элемент. Таким образом, родитель и ребенок выглядят следующим образом:

Parent(zh):
  host = zookeeper_get_connected_host(zh)
  client_id = zoo_client_id(zh)
  if fork == 0
    exec child host client_id
  end

Child(host, client_id):
  ignore SIGINT
  zh = zookeeper_init(host, client_id)
  while(true)
    sleep
  end

Я протестировал это с помощью libzookeeper_mt-0.3.3, и он работает как описано. Некоторая гадость начинает извергаться из логов Zookeeper, когда вы делаете этот хак, что может быть неприятно. Если вы не можете игнорировать журналы, вы можете отключить их следующим образом:

zoo_set_debug_level((ZooLogLevel)0);

Это недокументированный способ в Zookeeper отключить ведение журнала.

0 голосов
/ 09 марта 2011

Это помогает:

http://www.delorie.com/gnu/docs/gdb/gdb_25.html

Похоже, вы можете сделать что-то вроде "thread apply [threadno] break lineno"

...