2016-12-21 4 views
2

У меня есть следующий код (source):Контрольная точка GDB в рутине простого Pthread?

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

#define NUM_THREADS 5 

void *PrintHello(void *threadid) { 
    long tid; 
    tid = (long)threadid; 
    printf("Hello World! It's me, thread #%ld\n", tid); 
    pthread_exit(NULL); 
} 

int main(int argc, char *argv[]) { 
    pthread_t threads[NUM_THREADS]; 
    int rc; 
    long t; 
    for (t=0; t<NUM_THREADS; t++) { 
    printf("In main: creating thread %ld\n", t); 
    rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t); 
    if (rc) { 
     printf("ERROR; return code from pthread_create() is %d\n", rc); 
     exit(-1); 
    } 
    } 

    // wait for all threads to die 
    pthread_exit(NULL); 
} 

Я компилировать с gcc -g main.c -o main -lpthread. Я использую GDB для отладки. Я хочу разместить точку останова на второй строке PrintHello, то есть на tid = (long)threadid, и остановить выполнение там (независимо от потока) и позволить мне делать такие вещи, как посмотреть на значение переменной threadid.

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

arrow

Однако при вводе в строке GDB print threadid я вернусь No symbol "threadid" in current context. и стрелка сразу подскакивает до некоторой точки останова, которые я поставил в основном():

im2

Я думаю, что это происходит потому, что «пауза» выполнение программы происходит в основном потоке, который не поток работает PrintHello. PrintHello управляется нитью t - так как это не поток, приостановленный GDB, он печатает сообщение hello world и существует сразу. К тому моменту, когда я набираю print threadid, этот поток уже мертв, и программа возвращается в main() ... следовательно, эффект.

Я попытался решить эту проблему, набрав что-то вроде break <LineNumber> thread <ThreadID>, но это не хорошо, поскольку в этой программе созданные потоки продолжаются в течение секунды. Таким образом, я никогда не нахожусь в точке, где info thread показывает все, кроме основного потока. По-человечески невозможно «поймать» программу в точке, где есть основной поток, а недавно созданный поток работает PrintHello - так как эта ситуация длится, я думаю, несколько микросекунд.

Пожалуйста, помогите мне достичь этой простой цели отладки, чтобы остановить выполнение любого потока, выполняющего PrintHello на линии tid = (long)threadid;.

ответ

0

Решил, в конце концов, не было большой проблемы. Вот инструкции, если у кого есть подобный вопрос:

  1. Compile с gcc -ggdb main.c -o main -lpthread (да, это -ggdb и не -g, по-видимому, чтобы сделать разницу)
  2. Запустите отладчик с gdb main или, в Emacs, с M-x gdb (и команда gdb -i=mi main)
    • важнейшем здесь: Emacs имеет по умолчанию переменной gdb-non-stop-settingset to t, что означает, что он пытается запустить GDB в режиме нон-стоп. Согласно документам, это НЕ то, что я хочу - мне нужен режим полной остановки. Таким образом, либо сделайте set-variable, либо поместите (setq gdb-non-stop-setting nil) в ваш файл инициализации (например, ~/.emacs.d/init.el). Только после того, как это будет сделано, вы должны запустить M-x gdb из Emacs ...
  3. (gdb) b 9 установить точку останова на строку 9
  4. (gdb) r запустить программу. Выполнение остановится, когда один из потоков достигнет линии 9, то есть tid = (long)threadid;. Все остальные потоки также остановятся! Отлично!
  5. (gdb) c для продолжения. Выполнение остановится, когда другой поток достигнет линии 9. Отлично!
  6. Продолжайте делать все, у нас есть желаемое поведение сейчас :)
Смежные вопросы