几个月前突然想看下协程相关的东西,于是下了demo跑了起来,测试代码如下
|
|
刚跑起来就core了
(gdb) bt
#0 0x00007fdfdf04bc90 in ?? ()
#1 0x00007fdfdeb20d9c in co_eventloop (ctx=0x25cdac0, pfn=0x0, arg=0x0)
at co_routine.cpp:779#2 0x000000000041021a in main (argc=3, argv=0x7ffcec531b28)
at /home/cai/soft/cppserver-c7/server/brocaststat/src/BrocastStat.cpp:58
|
|
这个是libco的内部函数,于是debug了下,发现初始化的时候地址是正常的,但是经过协程切换后这个函数地址的前几位被截断了,导致了地址失效。于是跑libco的example,一切正常,函数地址没有被截断。
所以问题就缩小到了切换协程的地方了,但是暂时没啥头绪,也搜不到相关的资料(libco的资料实在太少了)。
问题定位
某天晚上闲的发慌于是就翻了libco的源码,发现在初始化的时候,协程栈只有128k,也没看到扩容的地方,于是联想到是不是爆栈了,于是调大了栈后问题真的没出现了
问题分析
Breakpoint 1, save_stack_buffer (occupy_co=0x636790) at co_routine.cpp:584
584 stStackMem_t* stack_mem = occupy_co->stack_mem;
Missing separate debuginfos, use: debuginfo-install apr-1.4.8-3.el7.x86_64 apr-util-1.5.2-6.el7.x86_64 cyrus-sasl-lib-2.1.26-20.el7_2.x86_64 expat-2.1.0-10.el7_3.x86_64 glibc-2.17-157.el7_3.5.x86_64 libdb-5.3.21-19.el7.x86_64 libgcc-4.8.5-11.el7.x86_64 libstdc++-4.8.5-11.el7.x86_64 libuuid-2.23.2-26.el7_2.3.x86_64 nspr-4.11.0-1.el7_2.x86_64 nss-3.21.0-9.el7_2.x86_64 nss-softokn-freebl-3.16.2.3-14.4.el7.x86_64 nss-util-3.21.0-2.2.el7_2.x86_64 openldap-2.4.40-9.el7_2.x86_64 protobuf-2.5.0-8.el7.x86_64 zlib-1.2.7-17.el7.x86_64
(gdb) n
585 int len = stack_mem->stack_bp - occupy_co->stack_sp;
(gdb) n
587 if (occupy_co->save_buffer)
(gdb) p len
$1 = 148777
断点打在保存协程栈的函数,发现len是148777也就是145.29004kb,但是实际执行的只有128k,所以当协程切换的时候128k之外的就会被截断。讲道理libco是优化下,做栈自动扩容的,这个能避免不少坑,或者抛个异常到上层终止程序也好。