Linux多进程和多线程的一次gdb调试实例

https://typecodes.com/cseries/multilprocessthreadgdb.html
linux C/C++开发中gdb进行多进程和多线程的调试一直比较麻烦,在CSDN上看到高科的一篇文章《gdb调试多进程和多线程命令》比较有启发,这里就自己重新整理并做了一个GDB多进程/线程的调试实践 。
Linux多进程和多线程的一次gdb调试实例

文章插图
 
1 原文整理默认设置下,在调试多进程程序时gdb只会调试主进程 。gdb7以上的版本(gdb --version)支持多进程调试,只需要设置好follow-fork-mode(fork追踪模式)以及detach-on-fork(指示GDB在fork之后是否断开某个进程的调试)即可 。
这两个参数的设置命令分别是:set follow-fork-mode [parent|child],set detach-on-fork [on|off] 。
两者结合起来构成了GDB的调试模式:
follow-fork-mode detach-on-fork 说明 parent on GDB默认的调试模式:只调试主进程 child on 只调试子进程 parent off 同时调试两个进程,gdb跟主进程,子进程block在fork位置 child off 同时调试两个进程,gdb跟子进程,主进程block在fork位置查看gdb默认的参数设置:
(gdb) show follow-fork-modeDebugger response to a program call of fork or vfork is "parent".(gdb) show detach-on-forkWhether gdb will detach the child of a fork is on.(gdb)2 演示代码下面这段代码的主要流程就是在main函数中fork创建一个子进程,然后在父进程中又创建一个线程,接着就使用gdb进行调试(block子进程) 。注意,在调试设置断点的时候,由于之前调试的时候代码最前面没有加上这7行说明文字,所以设置断点的行号要加上7 。
/*** @FileName gdb_pthread.c * @Describe A simple example for the debug of multiprocess and multithreading using gdb in linux system. * @Author vfhky 2016-02-25 22:48 https://typecodes.com/cseries/multilprocessthreadgdb.html * @Compile gcc gdb_pthread.c -g -o gdb_pthread * @Reference http://blog.csdn.net/pbymw8iwm/article/details/7876797 */#include <stdio.h>#include <pthread.h>#include <sys/types.h>#include <unistd.h>//Parent process handle.void Parent();//Child process handle.void Child();//Parent process handle after generate a thread.void * ParentDo( char *argv );int main( int argc, const char **argv ){ int pid; pid = fork(); if(pid != 0) //add the first breakpoint. Parent(); else Child(); return 0;}//Parent process handle.void Parent(){ pid_t pid = getpid(); char cParent[] = "Parent"; char cThread[] = "Thread"; pthread_t pt; printf( "[%s]: [%d] [%s]n", cParent, pid, "step1" ); if( pthread_create( &pt, NULL, (void *)*ParentDo, cThread ) ) { printf( "[%s]: Can not create a thread.n", cParent ); } ParentDo( cParent ); sleep(1);}void * ParentDo( char *argv ){ pid_t pid = getpid(); pthread_t tid = pthread_self(); //Get the thread-id selfly. char tprefix[] = "thread"; printf( "[%s]: [%d] [%s] [%lu] [%s]n", argv, pid, tprefix, tid, "step2" ); //add the second breakpoint. printf( "[%s]: [%d] [%s] [%lu] [%s]n", argv, pid, tprefix, tid, "step3" ); return NULL;}void Child(){ pid_t pid = getpid(); char prefix[] = "Child"; printf( "[%s]: [%d] [%s]n", prefix, pid, "step1" ); return;}已知如果直接运行程序,那么输出的内容如下:
[vfhky@typecodes pthread_key]$ gdb_pthread[Parent]: [22648] [step1][Parent]: [22648] [thread] [139722467432256] [step2][Parent]: [22648] [thread] [139722467432256] [step3][Thread]: [22648] [thread] [139722450630400] [step2][Thread]: [22648] [thread] [139722450630400] [step3][Child]: [22649] [step1][vfhky@typecodes pthread_key]$3 gdb调试3.1 设置调试模式和Catchpoint
设置调试父子进程,gdb跟主进程,子进程block在fork位置 。
[vfhky@typecodes pthread_key]$ gdb gdb_pthreadGNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-80.el7Copyright (C) 2013 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law. Type "show copying"and "show warranty" for details.This GDB was configured as "x86_64-redhat-linux-gnu".For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>...Reading symbols from /home/vfhky/bin/gdb_pthread...done.(gdb) set detach-on-fork off#####catch让程序在发生某种事件(fork、异常throw、异常catch、动态库加载等)的时候停止运行(gdb) catch fork Catchpoint 1 (fork)(gdb) info bNum Type Disp Enb Address What1 catchpoint keep y fork(gdb)如下图所示:
Linux多进程和多线程的一次gdb调试实例

文章插图
 
3.2 开始gdb调试(gdb) r ####运行到断点/捕捉点(第17行处的fork函数,23873是子进程PID)Starting program: /home/vfhky/bin/gdb_pthread [Thread debugging using libthread_db enabled]Using host libthread_db library "/lib64/libthread_db.so.1".Catchpoint 1 (forked process 23873), 0x00007ffff709b50c in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:130130 pid = ARCH_FORK ();(gdb) bt #####查看堆栈情况#0 0x00007ffff709b50c in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:130#1 0x00000000004007b4 in main (argc=1, argv=0x7fffffffe4c8) at gdb_pthread.c:17(gdb) info threads #######显示运行的线程信息(23869是父进程的PID) Id Target Id Frame * 1 Thread 0x7ffff7fe1740 (LWP 23869) "gdb_pthread" 0x00007ffff709b50c in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:130(gdb) info inferiors ######显示正在调试的进程:1前面的星号表示当前调试的进程(PID 23869) 。Num Description Executable * 1 process 23869 /home/vfhky/bin/gdb_pthread (gdb) info b ######列出所有断点和捕捉点,此时已经hit 1 time,即捕捉到了一次fork事件Num Type Disp Enb Address What1 catchpoint keep y fork, process 23873 #####子进程23873 catchpoint already hit 1 time(gdb)


推荐阅读