python gdb调试_如何自学Python用gdb调试python多线程代码-记一次死锁的发现

|版权:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。如有问题,可以邮件:wangxu198709@gmail.com

前言

相信很多人都有使用过sqlite3的经验,一年前因为项目上的需要,写了一个基于sqlite3的持久化队列库(persist-queue),已经发布在pypi上有段时间了。 前段时间,一下子来了两个issues,一个是关于in-memory database的support,一个是sqlite3 队列性能的问题。在数据量不大的情况下,sqlite的队列会在某些情况下出现:

sqlite3.OperationalError: database is locked

在修复上面的问题的时候,注意到,在多线程的情况下更容易触发上面的exception,并且比较怪的是,有时测试还有两个问题: 1. 出现死锁,并且CPU占用会一直保持在100%。

在程序里面下断点(import pdb;pdb.set_trace())和log都不好使,关键是无法精确定位到所有线程在当时的运行状态。

找了不少方法,最后还是发现了管用的方法,使用大名鼎鼎的:   gdb

相比pdb,gdb有以下几个优点:

不需要显示的下断点,如"import pdb;pdb.set_trace()"

可以方便的调试多线程程序,允许你调试过程中切换调试线程。很多python debug是不支持的如 winpdb, pydevd

如果python解释器core dump了,生成的core dump文件可以直接用gdb 来分析,而gdb只能望“dump”兴叹了。

Python给gdb准备了以extension,方便用户不仅可以查看Python解释器的运行情况,还可以查看用户程序的运行情况。

python gdb extension在gdb的环境下提供了如下几个py-*命令

py-list查看当前python应用程序上下文

py-bt          查看当前python应用程序调用堆栈

py-bt-full   查看当前python应用程序调用堆栈,并且显示每个frame的详细情况

py-print    查看python变量

py-locals   查看当前的scope的变量

py-up         查看上一个frame

py-down    查看下一个frame

环境准备

首先按照需要的各种调试用到的包

1. 安装gdb, 调试的主要工具

sudo apt-get install gdb

2. 安装python-dbg, 用来在调试的时候看到python源代码的call stack

sudo apt-get install python-dbg

这里面我都是用的python2.7,如果用的是python3.5,需要对应的安装python3.5-dbg

重现问题(死锁,Hung process)

$ tox -e py27

py27 develop-inst-nodeps: /home/peter/Documents/persist-queue

py27 installed: configparser==3.5.0,cov-core==1.15.0,coverage==4.4.1,enum-compat==0.0.2,enum34==1.1.6,eventlet==0.21.0,flake8==3.5.0,funcsigs==1.0.2,greenlet==0.4.12,mccabe==0.6.1,mock==2.0.0,nose2==0.6.5,pbr==3.1.1,-e git+https://github.com/peter-wangxu/persist-queue@d26561e3c7c9a35fd75ddedf0a023a7dcbd563a9#egg=persist_queue,pkg-resources==0.0.0,pycodestyle==2.3.1,pyflakes==1.6.0,six==1.11.0,virtualenv==15.1.0

py27 runtests: PYTHONHASHSEED='564480154'

py27 runtests: commands[0] | nose2 --with-coverage --coverage-report xml --coverage-report term

WARNING:persistqueue.sqlbase:auto_commit=False is still experimental,only use it with care.

....

上面的测试永远不会返回,悲伤啊。。

使用gdb加载symbols

1. 首先找到进程号

$ ps -ef | grep tox

peter 9376 1777 0 15:10 pts/17 00:00:00 /usr/bin/python3 /usr/bin/tox

peter 9409 9376 67 15:10 pts/17 01:04:14 /home/peter/Documents/persist-queue/.tox/py27/bin/python2.7 .tox/py27/bin/nose2 --with-coverage --coverage-report xml --coverage-report term

peter 9913 9639 0 16:45 pts/18 00:00:00 grep --color=auto tox

上面的 9409 就是我卡住的进程了。

接下来就是使用gdb调试: sudo gdb python -p 9409

记得用用sudo,否则symbols有可能无法加载成功

sudo gdb python -p 9409

GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1

Copyright (C) 2016 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later

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-linux-gnu".

Type "show configuration" for configuration details.

For bug reporting instructions, please see:

.

Find the GDB manual and other documentation resources online at:

.

For help, type "help".

Type "apropos word" to search for commands related to "word"...

Reading symbols from python...Reading symbols from /usr/lib/debug/.build-id/cd/e2c487269892a2815c715667ae336984b82b0c.debug...done.

done.

Attaching to program: /usr/bin/python, process 9409

[New LWP 9427]

[Thread debugging using libthread_db enabled]

Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

0x00007fb923247827 in futex_abstimed_wait_cancelable (private=0, abstime=0x0, expected=0, futex_word=0x152af60) at ../sysdeps/unix/sysv/linux/futex-internal.h:205

205 ../sysdeps/unix/sysv/linux/futex-internal.h: No such file or directory.

更多:如何自学Python用gdb调试python多线程代码-记一次死锁的发现

https://www.002pc.comhttps://www.002pc.com/python/1684.html

你可能感兴趣的死锁,多线程,python,gdb,调试,代码

linux c调试工具deadlock linux死锁

所谓死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这

php zbarcode扩展PHP使用Pthread实现的多线程操作实例

本文实例讲述了PHP使用Pthread实现的多线程操作。分享给大家供大家参考,具体如下:

南京领添 php使用GDB调试PHP代码,解决PHP代码死循环问题

初步断定是PHP代码中发生死循环。

下面通过一段代码展示如何解决PHP死循环问

mysql导出表结构和存储过程mysql死锁怎么解决?

MySQL有两种死锁处理方式:● 等待,直到超时(innodb_lock_wait_timeout=50s),自动回滚事务。

mysql 导出sql表数据怎么样避免mysql死锁

第二电脑网认为此文章对《mysql 导出sql表数据怎么样避免mysql死锁》说的很在理。如何尽可能避免死锁:1、以固定的顺序访问表和行。比如两个更新数据的事务,事务A 更新数据的

asp.net 修改数据库连接ASP.NET 远程调试

远程调试,可以再你本机调试远程代码,比较适合团队开发或者你本机没有调试环境的情况下。调试步骤:1、本机必须要有Vistual Studio的远程

电脑如何调屏幕亮度Linux最大线程数限制及当前线程数查询

Linux最大线程数限制及当前线程数查询,有需要的朋友可以参考下。

False

PHP的线程安全与非线程安全版本的区别

Windows版的PHP从版本5.2.1开始有Thread Safe(线程安全)和None Thread Safe(NTS,非线程安全)之分,这两者不同在于何处?到底应该用哪种?

0踩

0 赞

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值