如何进行多线程调试

最近需要调试多线程程序,就试着在网上搜了些资料。正好整理了一个例子方便自己理解和记忆

static void* WorkThread1(void *threadId)
{
    int64 tid = (int64)threadId;    
    int i = 0;
    while(i <= 60)
    {
        i++;
        sleep(1);
        printf("Hello [%d]\n",i); //b2
    }
    printf("After Sleep, [%lld]\n", tid); //b3
    Myfunc1();
    return NULL; //建议在此设置一个断点
}
 
static void* WorkThread2(void *threadId)
{
    int64 tid = (int64)threadId;
    int i = 0;
    while(i <= 60)
    {
        i++;
        sleep(1);
        printf("Hello [%d]\n",i); //b4
    }
    printf("After Sleep, [%lld]\n", tid); //b5
    Myfunc2();
    return NULL; //建议在此设置一个断点
}
 
int32 Task15()
{
    pthread_t threadId1, threadId2;
    int32 ret = 0;
    if ((ret = pthread_create(&threadId1, NULL, WorkThread1, (void*)1)))
    {
        perror("Thread 1 create");
        return 0;
    }
 
    if ((ret = pthread_create(&threadId2, NULL, WorkThread2, (void*)2)))
    {
        perror("Thread 2 create");
    }
 
    ret = pthread_join(threadId1, NULL); //主线程在此等待
    if(ret != 0)
    {
        printf("tid:[%lld]\n",(uint64)threadId1);
        perror("Thread Join");
    }
 
    ret = pthread_join(threadId2, NULL);
    if(ret != 0)
    {
        printf("tid:[%lld]\n",(uint64)threadId1);
        perror("Thread Join");
    }
 
    return 0; 
}


假设可该程序的可执行程序为mytest

则通过gdb进行上述程序的多线程调试如下

>gdb mytest

>r 15  //假设程序在执行时需要带参数15 才会运行Task15(./mytest 15), 则需要在gdb调试时,使用r 15命令

[New Thread0x7ffff63a8710 (LWP 13315)]

[New Thread0x7ffff5ba7710 (LWP 13316)]

Hello [1]

Hello [1]

Hello [2]

Hello [2] 

Hello [3]

Hello [3]

^C//从运行中退出来,我认为这个时候所有线程都被suspend

>

Program receivedsignal SIGINT, Interrupt.

0x00007ffff7bc8da5 inpthread_join () from /lib64/libpthread.so.0

>info threads //查看线程运行状态,带*号的为当前线程

  3 Thread 0x7ffff5ba7710 (LWP 13316)  0x00007ffff68a607d in nanosleep () from/lib64/libc.so.6

  2 Thread 0x7ffff63a8710 (LWP 13315)  0x00007ffff68a607d in nanosleep () from/lib64/libc.so.6

* 1 Thread0x7ffff7fbc320 (LWP 13312) 0x00007ffff7bc8da5 in pthread_join () from /lib64/libpthread.so.0


>thread //查看当前所在线程

[Current thread is 1(Thread 0x7ffff7fbc320 (LWP 13312))]


>bt //查看当前线程的执行位置

#0  0x00007ffff7bc8da5 in pthread_join () from/lib64/libpthread.so.0

#1  0x00000000004053e9 in Task15 () atmytest.c:837 //上述代码是从我的测试代码中抽出来的部分,行号请忽略

#2  0x00000000004087d1 in main (argc=3,argv=0x7fffffffe2f8) at ipc1_demo.c:126


>thread 2 //切换到线程2

[Switching to thread 2(Thread 0x7ffff63a8710 (LWP13315))]#0  0x00007ffff68a607d in nanosleep () from /lib64/libc.so.6

 

>bt //查看线程2的当前执行位置

#0  0x00007ffff68a607d in nanosleep () from /lib64/libc.so.6

#1  0x00007ffff68a5e9cin sleep () from /lib64/libc.so.6

#2  0x00000000004055fd in WorkThread1(threadId=0x1) at mytest.c:780  -----------> 从这里看出他是工作线程1

#3  0x00007ffff7bc85f0 instart_thread () from /lib64/libpthread.so.0

#4  0x00007ffff68d784d in clone () from/lib64/libc.so.6

#5  0x0000000000000000 in ?? ()


>thread 3 //切换到线程3

[Switching to thread 3(Thread 0x7ffff5ba7710 (LWP 13316))]#0 0x00007ffff68a607d innanosleep () from /lib64/libc.so.6

 

>bt //查看线程3的当前执行位置

#0  0x00007ffff68a607d in nanosleep () from /lib64/libc.so.6

#1  0x00007ffff68a5e9cin sleep () from /lib64/libc.so.6

#2  0x00000000004054e7 in WorkThread2 (threadId=0x2) at mytest.c:805 --------------->他是工作线程2

#3  0x00007ffff7bc85f0 instart_thread () from /lib64/libpthread.so.0

#4  0x00007ffff68d784d in clone () from/lib64/libc.so.6

#5  0x0000000000000000 in ?? ()


>b 806 thread 3 //在线程3上设置断点

>b 808 thread 3

>b 781 thread 2 //在线程2上设置断点

>b 783 thread 2 //建议在线程退出return的时候加上断点,因为如果不加,当前线程退出后,gdb就挂住了...

>info b //确认断点情况,(断点号与上面代码标注的有点偏差,且线程退出的断点未显示出来)

Num     Type           Disp Enb Address            What

2       breakpoint     keep y  0x00000000004054e7 inWorkThread2(void*) at mytest.c:806 thread 3

        stop only in thread 3

3       breakpoint     keep y  0x00000000004054ff in WorkThread2(void*) at mytest.c:808 thread 3

        stop only in thread 3

4       breakpoint     keep y  0x00000000004055fd in WorkThread1(void*) at mytest.c:781 thread 2

        stop only in thread 2

5       breakpoint     keep y  0x0000000000405615 inWorkThread1(void*) at mytest.c:783 thread 2

        stop only in thread 2


>continue //如果直接continue,则会所有线程同时执行,24,两个断点,任何一个都有可能被打断

>set scheduler-locking on//通过该条命令使得:仅当前线程执行

>thread //确认当前线程

[Current thread is 3(Thread 0x7ffff5ba7710 (LWP 13316))]

>c //继续执行

>n //单步执行

>info b //查看breakpoint信息,将循环中的断点disable

Num     Type           Disp Enb Address            What

2       breakpoint     keep y  0x00000000004054e7 inWorkThread2(void*) at mytest.c:806 thread 3

        stop only in thread 3

        breakpoint already hit 6 times

3       breakpoint     keep y  0x00000000004054ff in WorkThread2(void*) at mytest.c:808 thread 3

        stop only in thread 3

4       breakpoint     keep y  0x00000000004055fd in WorkThread1(void*) at mytest.c:781 thread 2

        stop only in thread 2

        breakpoint already hit 5 times

5       breakpoint     keep y  0x0000000000405615 inWorkThread1(void*) at mytest.c:783 thread 2

        stop only in thread 2

> disable 2 b2禁止掉

>c

Continuing.

Hello [9]

Hello [10]

Hello [11]

Hello [12]

Hello [13]

Hello [14]

Hello [15]


Breakpoint 3,WorkThread2 (threadId=0x2) at mytest.c:808

808         printf("After Sleep,[%lld]\n", tid);

>until 814 //执行至814 b5

>s //进入函数myfunc

>finish //完成函数,至函数返回语句

>n //从函数返回

>thread  2//切换到thread 2

>c//执行thread 2

Hello [7]

Hello [8]

Hello [9]

Hello [10]

Hello [11]

Hello [12]

Hello [13]

Hello [14]

Hello [15]

Hello [16]

Hello [17]

Hello [18]

Hello [19]

Hello [20]

Hello[21]

Hello[22]

Hello[23]

Hello[24]

Hello[25]

Hello[26]

Hello[27]

Hello[28]

Hello[29]

Hello[30]

Hello[31]

Hello[32]

Hello[33]


>thread 1 //切回到主线程

>set   scheduler-lockingoff //线程并行执行

>c

>c

>c

Program exited with code 01.

进程结束,调试结束


另外:

调试多线程时,由于可能还没来的及调试线程,线程就已经完成工作退出了, 因此,可以使用上述例子中的方法,在每个线程中,一起来先让他sleep一段时间,待gdb进入,将所有线程中断,可以调试时,再跳过sleep进行真正的调试。


在对多线程的守护进程进行调试时,可以直接gdb进入调试模式,之后attach <pid>,其中pid为待调试进程,一旦attach到该进程,该进程的所有线程都将进入suspend状态,此时就可如上所述一样,设置断点进行调试。


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值