zhaodongzhi opened a new issue, #1776: URL: https://github.com/apache/incubator-brpc/issues/1776
**Describe the bug (描述bug)** ### 问题1  栈被损坏  1. 假设bthread1在pthread1上调用return_keytable最终会调用用户注册的bthread local析构函数,如果这个析构函数调用了bthread_mutex_lock等会导致bthread切换的函数则会使得执行return_keytable之后bthread1切换到另一个线程pthread2上 2. 由于g还是用的pthread1上的thread local tls_task_group,在pthread2调用g->set_remained(TaskGroup::_release_last_context, m);会使得pthread1提前将bthread1的stack释放掉,如果此时另一个bthread2申请到了这个stack则会导致bthread1和bthread2共用了同一个stack,互相踩栈导致上述现象 ### 问题1修复  可以移动g = tls_task_group到bthread local析构函数之后的位置修复 ### 问题2 **应用上述修复后会遇到第二个问题,是由于gcc编译优化thread local访问方式结合bthread跨线程调度导致的** <img width="871" alt="image" src="https://user-images.githubusercontent.com/6293650/172087565-1d162523-3a23-4e4e-9b8a-16b91b20491c.png"> bthread meta中记录的local_storage.keytable是正确的但是tls_bls.keytable被设置为null导致获取不到bthread注册的bthread local变量引起coredump    可以看到编译优化后将tls_bls的地址保存在了寄存器r15中 我们知道如果用户注册的bthread local析构函数如果存在引起bthread切换的调用,return_keytable可能会触发bthread从pthread1切换到pthread2上,这里由于gcc将tls_bls的地址保存在r15寄存器的优化会导致在pthread2执行 tls_bls.keytable = NULL; 这个操作实际上是将pthread1的tls_bls.keytable设置为null了,而此时pthread1上运行的bthread2可能设置过tls_bls.keytable是不为null的,也就导致了我们上面看到的现象,pthread1上的bthread2获取不到自己设置的bthread local变量了 ### 问题2修复 这个问题使用原子变量或memory fence也解决不了,因为这两者对gcc来说只能组织缓存值的优化不能阻止缓存地址的优化 可以将 KeyTable* kt = tls_bls.keytable; 修改为 KeyTable* kt = m->local_storage.keytable 判定上是等价的,但是可以先避开gcc 缓存tls_bls地址的优化 也可以考虑将thread local关键字声明的tls_bls用pthread_getspecific函数api替代,因为gcc无法对通过pthread_getspecific获取到的thread local做缓存优化,不过这样改的会有点多 **To Reproduce (复现方法)** 自己写一个注册bthread local 析构函数中调用bthread_mutex_lock的代码多线程并发启动,停止bthread以触发bthread_local析构 **Expected behavior (期望行为)** **Versions (各种版本)** OS: Compiler: brpc: protobuf: **Additional context/screenshots (更多上下文/截图)** -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
