如何将gdb调试限制为一次只能调试一个线程

41

我想通过控制线程执行顺序来调试一个多线程程序,我正在使用C++和gdb。除了主线程外,我还有两个线程(用于示例程序),我想在保持另一个线程停止的同时调试一个线程。

这是我编写的示例程序:

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

#define NUM_THREADS 2

using namespace std;

void * run (void *) {
  for (int i = 0; i < 3; ++i) {
    sleep(1);
    cout << i << " " << pthread_self() << endl;
  }
  pthread_exit(NULL);
}

int main (int argc, char** argv) {
  cout << "Start..." << endl;
  int rc;

  pthread_t threads[NUM_THREADS];
  for (int i = 0; i < NUM_THREADS; ++i) {
    rc = pthread_create(&threads[i], NULL, run, NULL);
    if (rc) {
      cout << "pthread_create returned error: " << rc << endl;
      exit(-1);
    }
  }
  pthread_exit(NULL);

}

我在使用gdb时,在带有sleep(1)的代码行处设置了断点。然后运行程序,启动了三个线程(其中线程2和3是pthread),并且程序正在线程2上等待(在sleep(1)处)。现在,我想让线程3继续执行,而保持在线程2中,并通过在gdb中执行c命令来逐步执行线程2。

我尝试过set scheduler-locking on,但它似乎没有按照我的期望工作。当我位于线程2中时,我使用set scheduler-locking on,然后执行几次continue(到目前为止一切顺利,我仍然在线程2中),然后切换到线程3,使用set scheduler-locking oncontinue,但由于某种原因,我又回到了线程2中...根据我的理解,这不应该发生。我是否遗漏了什么?

2个回答

29
正如TazMainiac所说,调度器锁定对于单步执行很有用,但"模式"必须设置为"step"。
set scheduler-locking step

您可以参考TazMainiac提供的链接,其中提到了同样的内容:

http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_node/gdb_39.html

步进模式针对单步调试进行了优化。它通过抢占当前线程来防止其他线程“占用提示符”,从而实现单步调试。


1
在我的环境中,似乎设置调度程序锁定功能是有效的,但设置调度程序锁定步骤却无效。我正在使用GNU gdb (GDB) SUSE (7.1-3.12)。 - Bai Bing

15
似乎调度器锁定只在单步或下一步时有用。一旦你继续进行当前线程,它们就全部运行了,下一个到达断点的线程将抓住提示符。至少,这是我根据手册的解释。

http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_node/gdb_39.html

因此,一旦您进入线程3,其他线程将停止运行,只要您进行步骤/下一步操作,它们就不会运行。但是一旦您继续执行,它们都会运行,并且下一个线程(在您的示例中为2)遇到sleep(1)中断点时将抓取提示符。

也许让所有线程都到达sleep,然后一次只继续一个线程。


谢谢提供的链接...事实证明,即使在线程3中执行set scheduler-locking on后使用next命令,它仍然会将控制权转移到线程2。(如果我使用step命令,则不会这样,但是逐个指令地步进库代码非常痛苦。)除了set scheduler-locking on之外,是否有其他命令可以解决这个问题? - Yogeshwer Sharma
似乎没有更好的方法,而您已经澄清了问题。因此,接受这个答案。 - Yogeshwer Sharma
2
使用 set scheduler-locking on 被认为是依赖于操作系统的。尽管如此,在我的系统上运行良好(Linux 4.4.0 内核,gdb 7.11.1,Ubuntu 16.04)。 - Jan Wielemaker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接