如何调试程序挂起的原因?

时间:2016-10-13 15:03:11

标签: c multithreading gdb pthreads

我有一个包含2个线程的程序,其中一个重绘显示(使用ncurses),另一个在串口上运行inout处理,输出一些信息。

我发现在某些时候,第二个帖子因为我不知道的原因而挂起。如果:

,如何找到问题的根源
  1. 我无法调试第二个线程中发生的事情,因为libthread_db和libpthread在我的系统上不匹配,gdb拒绝提供线程调试。
  2. 挂起的线程通过对非阻塞文件描述符的selectread的顺序调用执行处理。
  3. 用Cntrl-C放入gdb并恢复程序后,线程被取消;此外,它会处理卡在串口接收缓冲区中的所有数据。
  4. 是否有任何提示或技巧可以帮助我找到问题的根源并确定悬挂的原因?

    更新。使用strace运行会在跟踪中将这些行打包给我:

    waitpid(-1, 0xbfdcdfd0, 0)           = ? ERESTARTSYS (To be restarted)
    --- SIGCHLD (Child exited) @ 0 (0) ---
    --- SIGCONT (Continued) @ 0 (0) ---
    

    据我所知,这对应于我在程序中看到挂起的时间,用C-z暂停它并查看跟踪文件(在整个程序完成之前没有写任何新内容)。每次重新启动线程都未更改后。

    所以,这意味着有一个'流氓'waitpid电话。我确信它在我的代码中的任何地方都没有以裸露的形式出现。遗憾的是,gdb没有在它上面设置断点 - 必须是某处的剥离符号问题。

1 个答案:

答案 0 :(得分:1)

  

是否有任何提示或技巧可以帮助我找到问题的根源并确定悬挂的原因?

显而易见的答案是在挂起的线程上使用strace来查看它正在做什么。

一个常见的错误是你希望读取一些字节数,并像这样循环:

while (bytes_remaining > 0) {
  int n = read(..., bytes_remaining);
  if (n == -1) { 
    // handle read error ...
    break;
  }
  // save data we just got ...
  bytes_remaining -= n;
  // loop to read more data
}

此处的问题是read可能会在0上返回EOF,并且您将永远循环播放。在strace这将立即显而易见。

如果不是这样,你可以做的另一件事(假设Linux)是将GDB附加到挂起的线程而不是进程。