CyberRT 一个多线程并发的bug

CyberRT 一个多线程并发的bug

场景

多线程去调用cyber GlobalData中Register接口,比如RegisterNode、RegisterChannel、RegisterService、RegisterTaskName,入参必须填相同的。
都会出现coredump。

分析

比如如下test代码:

  std::vector<std::thread> threads;for (int i = 0; i < 20; ++i) {threads.emplace_back([]() {while(1) {apollo::cyber::common::GlobalData::RegisterService("testminisim/test_register_msg");usleep(100);}});}

几乎必现,coredump堆栈如下,截取部分:

#0  0x00007ffa0fc69b50 in std::basic_streambuf<char, std::char_traits<char> >::xsputn(char const*, long) () from /lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00007ffa0fc5b824 in std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) () from /lib/x86_64-linux-gnu/libstdc++.so.6
#2  0x00007ffa1bd5111f in std::operator<< <char, std::char_traits<char>, std::allocator<char> > (__str=..., __os=...) at /usr/include/c++/9/bits/basic_string.h:2316
#3  apollo::cyber::common::GlobalData::RegisterService (service="determinism/epoch_register") at cyber/common/global_data.cc:223

具体是挂在了这行代码:

AWARN << "Service name hash collision: " << service << " <=> " << *name;

结合上面的堆栈,可以看出是在<<*name的时候挂了,有经验的朋友,看到挂到这里就能大致猜出来肯定是踩内存了。
所以开启asan后,发现确实打出了报告,asan的报告这里就不贴了,asan很明确的打出了AddressSanitizer: heap-use-after-free on address xxx。

再看看cyber这个函数的代码:

uint64_t GlobalData::RegisterService(const std::string& service) {auto id = Hash(service);while (service_id_map_.Has(id)) {std::string* name = nullptr;service_id_map_.Get(id, &name);if (service == *name) {break;}++id;AWARN << "Service name hash collision: " << service << " <=> " << *name;}service_id_map_.Set(id, service);return id;
}

这里service_id_map_是cyber实现的AtomicHashMap,本身的Get和Set都是线程安全的,但是填到Get函数的&name是个二级指针,也就是拿到的*name其实是AtomicHashMap table中的value。

比如同名service入参场景下:

  1. 线程1发现id不在service_id_map_中,于是成功Set完事;
  2. 这时候线程2和线程3同时执行到Get操作,线程3成功break出去执行Set,线程2这个时候才执行下面的比较,这个时候线程2的name已经被线程3写入,可能还没写完就被线程2用来operator= 和 operator<< 操作。

其实可以看到cyber其他用到AtomicHashMap的地方,都会对Get到的value做加锁动作,唯独这里没有做加锁动作。
比如这里:

template <typename T>
void DataDispatcher<T>::AddBuffer(const ChannelBuffer<T>& channel_buffer) {std::lock_guard<std::mutex> lock(buffers_map_mutex_);auto buffer = channel_buffer.Buffer();BufferVector* buffers = nullptr;if (buffers_map_.Get(channel_buffer.channel_id(), &buffers)) {buffers->emplace_back(buffer);} else {BufferVector new_buffers = {buffer};buffers_map_.Set(channel_buffer.channel_id(), new_buffers);}
}

buffers_map_是AtomicHashMap类型的,在AddBuffer中通过Get出来的buffers,这里会加锁。

还有这里:

inline void DataNotifier::AddNotifier(uint64_t channel_id, const std::shared_ptr<Notifier>& notifier) {std::lock_guard<std::mutex> lock(notifies_map_mutex_);NotifyVector* notifies = nullptr;if (notifies_map_.Get(channel_id, &notifies)) {notifies->emplace_back(notifier);} else {NotifyVector new_notify = {notifier};notifies_map_.Set(channel_id, new_notify);}
}

notifies_map_也是AtomicHashMap类型,在AddNotifier也是做了加锁操作。

至此,原因清楚了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/634225.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为什么需要放行回源IP

为什么需要放行回源IP 网站以“独享模式”成功接入WAF后&#xff0c;所有网站访问请求将先经过独享引擎配置的ELB然后流转到独享引擎实例进行监控&#xff0c;经独享引擎实例过滤后再返回到源站服务器&#xff0c;流量经独享引擎实例返回源站的过程称为回源。在服务器看来&…

C++初阶类与对象(三):详解复制构造函数和运算符重载

上次介绍了构造函数和析构函数&#xff1a;C初阶类与对象&#xff08;二&#xff09;&#xff1a;详解构造函数和析构函数 今天就来接着介绍新的内容&#xff1a; 文章目录 1.拷贝构造函数1.1引入和概念1.2特性 2.赋值运算符重载2.1运算符重载2.2放在哪里2.3运算符重载示例2.3.…

C++后端笔记

C后端笔记 资源整理一、高级语言程序设计1.1 进制1.2 程序结构基本知识1.3 数据类型ASCII码命名规则变量间的赋值浮点型变量的作用字符变量常变量 const运算符 二、高级语言程序设计&#xff08;荣&#xff09; 资源整理 C后端开发学习路线及推荐学习时间 C基础知识大全 C那…

【INTEL(ALTERA)】使用Quartus出现系统错误:找不到 MSVCR120.dll

说明 由于英特尔 Quartus Prime Pro Edition 软件 23.2 及更早版本存在一个问题&#xff0c;您在启动 Questa*-英特尔 FPGA Edition 时可能会看到此系统错误。此错误是由于安装 Questa*-英特尔 FPGA 版软件时未安装 Visual Studio 2013 的 Visual C 可再发行组件包。 此问题仅…

element中表格组件的row-class-name和class-name属性的使用以及无效处理

1.这两个属性的使用&#xff0c;row-class-name用在el-table标签上&#xff0c;class-name用在el-table-column标签上。两个属性即可绑定类名也可绑定函数 <!-- 这里是绑定函数&#xff0c;也可以绑定类名 --> <el-table :data"tableData" selection-chang…

时间格式 yyyyMMdd

// 转换时间格式 yyyyMMdd export function dateFn(date) {var timenew Date(date);var year time.getFullYear() //年var month ("0" (time.getMonth() 1)).slice(-2); //月var day ("0" time.getDate()).slice(-2); //日var mydate year month …

DB107-ASEMI插件小方桥DB107

编辑&#xff1a;ll DB107-ASEMI插件小方桥DB107 型号&#xff1a;DB107 品牌&#xff1a;ASEMI 正向电流&#xff08;Id&#xff09;&#xff1a;1A 反向耐压&#xff08;VRRM&#xff09;&#xff1a;1000V 正向浪涌电流&#xff1a;50A 正向电压&#xff08;VF&…

Linux指令(二)

1.指令&#xff1a;cd ~ 该指令表示进入家目录。 那么你可能会问了&#xff0c;什么是家目录呢&#xff1f; 定义&#xff1a;家目录&#xff0c;又叫主目录。实际上是指用户所在的根目录&#xff0c;例如&#xff1a;在windows系统下&#xff0c;我们的用户目录就是家目录&…

1.7 面试经典150题 - H指数

H指数 给你一个整数数组 citations &#xff0c;其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。 根据维基百科上 h 指数的定义&#xff1a;h 代表“高引用次数” &#xff0c;一名科研人员的 h 指数 是指他&#xff08;她&#xff09;…

java基础:求数组的最值

方法一&#xff1a;顺序查找 先假设数组第一个元素为最值&#xff0c;然后和数组里的数按顺序进行比较得出最值&#xff0c;所以叫顺序查找。 代码如下 package idea;public class arr_int {public static void main(String[] args) { // 初始化一个数组int[] arr {12…

OpenGL Assimp加载各类型模型(.obj、.fbx、.glb、.3ds)

1.简介 本博客以.glb格式为例&#xff0c;加载glb格式的3d模型&#xff0c;网上找了一圈&#xff0c;基本上都是根据OpenGL官方示例&#xff0c;加载.obj格式的3d模型。 下面以.obj和.glb格式的3D模型简单介绍一下。 常见的.obj格式的3D模型如下所示&#xff1a;纹理都已经被…

往docker中cloudbeaver的容器添加达梦数据库、impala数据库连接支持(cloudbeaver添加自定义数据连接)

cloudbeaver默认没有开放impala连接&#xff0c;更不会支持国产数据库了 docker安装运行cloudbeaver可以参考文章&#xff1a;docker安装运行CloudBeaver并设置默认语言为中文 本文跳过cloudbeaver镜像拉取&#xff0c;直接就开始实现自定义数据库连接功能 1、初始化cloudbe…

C语言——atoi函数解析

目录 前言 atoi函数的介绍 atoi函数的使用 atoi函数的模拟实现 前言 对于atoi函数大家可能会有些陌生&#xff0c;不过当你选择并阅读到这里时&#xff0c;请往下阅读&#xff0c;我相信你能对atoi函数熟悉该函数的头文件为<stdlib.h> 或 <cstdlib> atoi函数的…

VCG 曲面重建之滚球算法

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 滚球算法(BPA)是一种与alpha形状相关的曲面重建方法。直观地想象一个具有给定半径的3D球,我们把它扔在点云上。如果它击中任何3个点(并且它没有穿过这3个点),它就创造了一个三角形。然后,算法从现有三角形的边缘…

NTP在集群中如何优化部署浅谈

在集群中优化部署NTP&#xff08;Network Time Protocol&#xff09;主要涉及以下几个方面&#xff1a; 硬件和操作系统选择&#xff1a; 选择高性能的硬件&#xff0c;具备足够的处理能力和存储空间&#xff0c;以满足大量的时间请求。 选择支持NTP的操作系统&#xff0c;如…

基于springboot+vue的房屋租赁系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…

从 GPT1 - GPT4 拆解

从 GPT1 - GPT4 拆解 从 GPT1 - GPT4GPT1&#xff1a;更适用于文本生成领域GPT2&#xff1a;扩展数据集、模型参数&#xff0c;实现一脑多用&#xff08;多个任务&#xff09;GPT3&#xff1a;元学习 大力出奇迹InstructGPT&#xff1a;指示和提示学习 人工反馈强化学习 RLHF…

什么?2024年AMC8正式比赛提前20多分钟强制交卷?后续如何处理?

今天&#xff08;2024年1月19日&#xff09;17:00-17:40是2024年AMC8美国数学思维活动&#xff08;竞赛&#xff09;正式比赛的时间&#xff0c;全国报名参加AMC8比赛的孩子们按要求提前架设好了设备&#xff0c;准时按要求登录考试系统&#xff0c;17点准时开考。原计划是要考…

排序链表(LeetCode 148)

文章目录 1.问题描述2.难度等级3.热门指数4.解题思路参考文献 1.问题描述 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [4,2,1,3] 输出&#xff1a;[1,2,3,4]示例 2&#xff1a; 输入&#xff…

2023年全球软件架构师峰会(ArchSummit深圳站):核心内容与学习收获(附大会核心PPT下载)

本次峰会是一次重要的技术盛会&#xff0c;旨在为全球软件架构师提供一个交流和学习的平台。本次峰会聚焦于软件架构的最新趋势、最佳实践和技术创新&#xff0c;吸引了来自世界各地的软件架构师、技术专家和企业领袖。 在峰会中&#xff0c;与会者可以了解到数字化、AIGC、To…