前段时间在Pi上用Python和gtk搞了个应用,到最后测试阶段一直被闪退折磨。闪退是我自己起的名词,比如你玩手机的时候,玩得正高兴的时候,游戏莫名其妙的闪退了,你郁闷不,开发者其实更郁闷,因为闪退嘛,死都不知道怎么死的。
经过一周的追踪,用尽各种手段,终于让我发现一款神奇。先来说说事情的起因。
先省略几个小时的log。。。
- batching times: 1
- thread batching starts...
- set, ['?RD.EC', '9006.38']
- thread batching stopped.
- ('READDATA', ('COND', None, None), [('?RD.EC', None)])
- get ?RD.EC
- in {'?RD.EC': '9006.38'}
- batching times: 1
- thread batching starts...
- set, ['OHM:5']
- thread batching stopped.
- *** glibc detected *** python: double free or corruption (fasttop): 0x01b73a28 ***
- 已放弃
- pi@raspberrypi ~/calibration/cali04a $
复制代码 看到了吧,重复了几个小时的代码,突然间闪退了,就给你这么点答案,释放空指针,靠,这前不着村后不着地的python,你让我去给你查指针释放去?经人介绍,用pydb(Extended Python Debugger)来跑,无功而返,对于这种Segment fault,根本跟没用差不多嘛,pydb也就能调调正常的程序。- ('READDATA', ('COND', None, None), [('?RD.EC', None)])
- get ?RD.EC
- in {'?RD.EC': '225.04'}
- batching times: 1
- thread batching starts...
- set, ['OHM:1000']
- thread batching stopped.
- batching times: 1
- thread batching starts...
- set, ['?RD.EC', '450.25']
- thread batching stopped.
- ('READDATA', ('COND', None, None), [('?RD.EC', None)])
- get ?RD.EC
- in {'?RD.EC': '450.25'}
- *** glibc detected *** /usr/bin/python: double free or corruption (!prev)batching times: 1
- : 0x00c12800 ***
- 已放弃
- pi@raspberrypi ~/calibration/src_cali04a $
复制代码 好吧,逼急了上gdb吧,好歹知道是哪里的错误了。这里要吐槽下gtk用到的gdk,满篇的断言,真不知该夸你还是该扁你!- ('READDATA', ('COND', None, None), [('?RD.EC', None)])
- get ?RD.EC
- in {'?RD.EC': '22.50'}
- batching times: 1
- thread batching starts...
- set, ['OHM:10000']
- thread batching stopped.
- batching times: 1
- thread batching starts...
- set, ['?RD.EC', '45.01']
- thread batching stopped.
- ('READDATA', ('COND', None, None), [('?RD.EC', None)])
- get ?RD.EC
- in {'?RD.EC': '45.01'}
- batching times: 1
- thread batching starts...
- **
- Gdk:ERROR:/build/gtk+2.0-x7uJoT/gtk+2.0-2.24.10/gdk/gdkregion-generic.c:1206:miUnionO: assertion failed: (pReg->numRects<=pReg->size)
- bt
- [New Thread 0x47eff470 (LWP 15726)]
- [Thread 0x48eff470 (LWP 15725) exited]
- [New Thread 0x48eff470 (LWP 15727)]
- [Thread 0x47eff470 (LWP 15726) exited]
- [New Thread 0x47eff470 (LWP 15728)]
- [Thread 0x47eff470 (LWP 15728) exited]
- [New Thread 0x467bf470 (LWP 15729)]
- [Thread 0x48eff470 (LWP 15727) exited]
- [New Thread 0x48eff470 (LWP 15730)]
- Program received signal SIGABRT, Aborted.
- 0x40384bfc in raise () from /lib/arm-linux-gnueabihf/libc.so.6
- (gdb) bt
- #0 0x40384bfc in raise () from /lib/arm-linux-gnueabihf/libc.so.6
- #1 0x4038897c in abort () from /lib/arm-linux-gnueabihf/libc.so.6
- #2 0x4046bd2c in ?? () from /lib/arm-linux-gnueabihf/libc.so.6
- #3 0x4046bd2c in ?? () from /lib/arm-linux-gnueabihf/libc.so.6
- Backtrace stopped: previous frame identical to this frame (corrupt stack?)
- (gdb)
复制代码 上面报gdk error的地方已经被无数函数调用过,我用bt命令回溯stack,貌似也看不到啥有用的信息,谁让咱用的是多线程呢,好吧,接下来该大杀器出场了。- set, ['?RD.EC', '225.06']
- thread batching stopped.
- ('READDATA', ('COND', None, None), [('?RD.EC', None)])
- get ?RD.EC
- in {'?RD.EC': '225.06', '?NTC.T': 'None', 'ID': 'None'}
- batching times: 1
- thread batching starts...
- set, ['OHM:1000']
- thread batching stopped.
- **
- Gdk:ERROR:/build/gtk+2.0-x7uJoT/gtk+2.0-2.24.10/gdk/gdkregion-generic.c:1110:miUnionNonO: assertion failed: (y1 < y2)
- Fatal Python error: Segmentation fault
- Thread 0x474a6470:
- Thread 0x486b9470:
- File "/usr/lib/python2.7/threading.py", line 244 in wait
- File "/usr/lib/python2.7/threading.py", line 404 in wait
- File "/usr/lib/python2.7/threading.py", line 500 in start
- File "d:/workspace/calibration/cali_test.py", line 43 in timer_event
- File "/usr/lib/python2.7/threading.py", line 760 in run
- File "/usr/lib/python2.7/threading.py", line 552 in __bootstrap_inner
- File "/usr/lib/python2.7/threading.py", line 525 in __bootstrap
- Thread 0x4666f470:
- File "d:/workspace/calibration/basinterp.py", line 476 in run
- File "d:/workspace/calibration/cali_test.py", line 388 in plying
- File "/usr/lib/python2.7/threading.py", line 505 in run
- File "/usr/lib/python2.7/threading.py", line 552 in __bootstrap_inner
- File "/usr/lib/python2.7/threading.py", line 525 in __bootstrap
- Thread 0x45de1470:
- File "/usr/lib/python2.7/threading.py", line 244 in wait
- File "/usr/lib/python2.7/threading.py", line 668 in join
- File "d:/workspace/calibration/cali_test.py", line 255 in receiving
- File "/usr/lib/python2.7/threading.py", line 505 in run
- File "/usr/lib/python2.7/threading.py", line 552 in __bootstrap_inner
- File "/usr/lib/python2.7/threading.py", line 525 in __bootstrap
- Current thread 0x400d7210:
- File "d:/workspace/calibration/cali_test.py", line 127 in on_TextViewOfLog_size_allocate
- File "d:/workspace/calibration/cali_test.py", line 786 in main
- File "d:/workspace/calibration/cali_test.py", line 791 in <module>
- 段错误
- pi@raspberrypi ~/calibration/cali04a $
复制代码 看到这里爽伐?每个线程的stack都被完整的打印出来,找问题不跟玩似的,呵呵。问题就是出在最后这个on_TextViewOfLog_size_allocate,究其原因,我没有把gtk的窗口设成固定大小,又因为我有一个Frame在不停地变换长短不一的文字,所以整个窗体一会大一点一会小一点,gdk经过几个小时的折磨,终于不小心被自己的断言给干掉了gdkregion-generic.c:1110:miUnionNonO: assertion failed: (y1 < y2)
好了,就这样。对了,忘了说神器叫啥了,faulthandler,截至发帖版本是2.2,地址在:https://pypi.python.org/pypi/faulthandler,用法如下:
在你的python主程序启动前,加上如下代码,然后就等着兔子上门吧:- import faulthandler
- faulthandler.enable()
复制代码 有什么问题欢迎加入QQ群讨论,号码:204148284(开源硬件)
|