调试一个 Bus error 错误

PHP加载动态库Buserror问题
本文记录了一次解决PHP加载mongo.so时遇到Buserror的问题过程。通过strace跟踪发现,错误由mmap操作引起,进一步排查发现是由于扩展文件不完整导致。重新同步后问题得到解决。

遇到一部分主机运行 php 的时候报 Bus error 错误,直接退出。

# /path/to/php Bus error 

于是用 strace 跟踪了一下,看看到底是怎么回事。

# strace /path/to/php ... ... ... open("/path/to/php/lib/php/extensions/no-debug-non-zts-20090626/mongo.so", O_RDONLY) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\270\0\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0644, st_size=32636, ...}) = 0 mmap(NULL, 2309488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x2b1e8e689000 mprotect(0x2b1e8e6ba000, 2097152, PROT_NONE) = 0 mmap(0x2b1e8e8ba000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x31000) = 0x2b1e8e8ba000 --- SIGBUS (Bus error) @ 0 (0) --- +++ killed by SIGBUS +++ 

strace 的最后几行如上面所示,进程受到了一个 SIGBUS 信号,看起来是 mmap 引起的。从这几行里看,是 php 在加载 mongo 扩展 mongo.so 时出的错。搜索了一下,mmap 映射内存的时候,在映射超出文件大小范围的内存空间时,可能引发这个 SIGBUS 。就上面的结果看,fstat 的结果表明,文件大小是 32636 字节。而最后那个 mmap 的 offset 参数 0×31000 即 200704,的定位范围直接就超过了文件大小,所以就引发了这个错误。

考虑到这个问题只在部分主机上出现,所以应当不是 php 或者 mongo 扩展本身的 bug 。最后发现是通过 puppet 同步下来的 mongo.so 不完整,比正常的小了很多。重新同步后恢复正常。

由此也可以看出,在加载动态库时是根据 elf 文件中标记的段大小来映射内存的。所以就发生了在文件不完整时 mmap 出错的情况。

<think>我们正在处理用户关于Bus error错误的问题。用户希望了解该错误的产生原因及解决办法。 根据用户提供的引用: 引用[1]提到:除了Bus error (core dumped),可以检查系统日志(如dmesg)或运行程序时的核心转储日志,了解更详细的错误信息:`dmesg | grep -i bus`。 引用[2]提到:在Linux服务器上运行Python程序时,能够正常import自带的包,但无法import外在安装的包(如MySQL、pymongo等),只要执行这种import操作,Python就会自动退出,并报bus error错误。同时,MongoDB也无法访问,报connect failed错误。 引用[3]提到:在系统日志中出现了PCIe Bus Error: severity=Corrected, type=Physical Layer, id=00e8(Receiver ID)。 综合以上,我们可以将Bus error错误的原因和解决方法归纳如下: 原因: 1. 硬件问题:如内存故障、CPU缓存问题、PCIe设备故障等。引用[3]中提到的PCIe总线错误就是硬件问题的一种。 2. 软件问题:如程序访问了未对齐的内存地址(例如,某些架构要求数据访问必须对齐,否则会触发总线错误);或者程序访问了已经被释放的内存;或者系统库损坏等。 3. 文件系统问题:如磁盘损坏、文件系统损坏等,导致程序无法读取所需的文件(如Python导入的第三方库文件)。 4. 驱动问题:硬件设备的驱动程序存在缺陷。 解决方法: 1. 检查系统日志:使用`dmesg -T | grep -i bus`(加上-T参数可以显示可读的时间戳)或查看/var/log/messages等系统日志,定位具体的错误信息。例如,引用[3]中通过日志发现PCIe总线错误,这种错误如果频繁出现可能需要更换硬件。 2. 检查内存:运行内存测试工具(如memtest86+)来排除内存问题。 3. 检查硬件:如果日志中提示了特定的硬件设备(如PCIe设备),尝试更换硬件或插槽。 4. 检查文件系统:使用`fsck`检查文件系统是否有错误。 5. 检查程序:如果是特定程序(如Python)出现总线错误,考虑重新安装该程序及其依赖库。例如,引用[2]中Python无法导入第三方包的问题,可能是由于第三方包损坏或安装不完整导致。可以尝试重新安装Python和相应的包。 6. 更新驱动和固件:更新系统的BIOS/UEFI固件以及相关硬件的驱动程序。 针对引用[2]中提到的具体问题(Python导入第三方包报总线错误,同时MongoDB连接失败): - 可能是由于系统库损坏或磁盘问题导致程序无法读取必要的文件。可以尝试: a. 重新安装Python和pip,然后重新安装第三方包。 b. 检查磁盘坏道:使用`badblocks`或`smartctl`工具检查磁盘健康状况。 c. 如果MongoDB也无法连接,可能是由于MongoDB的服务文件损坏,尝试重新安装MongoDB。 另外,总线错误还可能由于操作系统内核问题引起,可以尝试更新操作系统内核。 总结步骤: 1. 查看系统日志(dmesg等),定位错误详情。 2. 根据日志指示,检查硬件(内存、磁盘、PCIe设备等)或软件(重新安装程序、库文件等)。 3. 进行必要的硬件测试和系统修复。 生成相关问题: 1. 如何查看Linux系统日志以诊断硬件错误? 2. 内存测试工具memtest86+的使用方法是什么? 3. 如何检查并修复损坏的文件系统? 4. 如何重新安装Python及其第三方包? 5. 如何更新Linux系统内核? </think>### Bus Error 错误原因及解决方法 #### 一、核心原因分析 1. **硬件故障或兼容性问题** - **内存故障**:内存条损坏或接触不良导致数据总线传输错误(如 ECC 内存校验失败)[^1][^3] - **PCIe 设备异常**:扩展卡(如网卡、显卡)与主板兼容性问题或物理损坏,触发总线错误 $$ \text{PCIe Bus Error: severity=Corrected, type=Physical Layer} $$ - **CPU 缓存故障**:处理器缓存损坏导致数据读取异常 2. **软件层面问题** - **未对齐内存访问**:程序尝试访问未按处理器要求对齐的内存地址(如 32 位系统访问奇数地址) - **驱动缺陷**:硬件驱动存在漏洞或不兼容(常见于显卡、网卡驱动)[^3] - **库文件损坏**:Python 等程序依赖的第三方库(如 MySQL/pymongo)文件损坏或版本冲突[^2] 3. **系统环境异常** - **文件系统损坏**:磁盘坏道导致关键系统文件读取失败 - **内核模块冲突**:自定义内核模块或 DKMS 驱动与系统不兼容 - **超频不稳定**:CPU/内存超频后总线时序紊乱 #### 二、诊断方法 ```bash # 1. 检查系统日志(关键步骤) dmesg -T | grep -i "bus\|error\|pcie" # 显示带时间戳的总线错误[^1][^3] # 2. 测试内存健康 memtester 2G 1 # 测试2GB内存,运行1轮 # 3. 检查磁盘坏道 sudo badblocks -v /dev/sda # 扫描sda磁盘 # 4. 验证库文件完整性(Python示例) ldd $(which python3) | grep "not found" # 检查缺失依赖 ``` #### 三、解决方案 | **问题类型** | **解决措施** | |--------------------|-----------------------------------------------------------------------------| | **硬件故障** | - 重新插拔内存条/扩展卡<br>- 更换故障硬件(重点检测内存/PCIe设备) | | **驱动问题** | - 更新内核:`sudo apt install --install-recommends linux-generic`<br>- 降级问题驱动 | | **Python 库异常** | - 重建虚拟环境:`python -m venv --clear new_env`<br>- 重装包:`pip install --force-reinstall pymysql` [^2] | | **文件系统损坏** | - 修复磁盘:`fsck -y /dev/sda1`<br>- 恢复备份库文件 | | **内存对齐问题** | 使用调试工具定位代码:<br>`gdb -ex "run" -ex "bt" ./program` | #### 四、高级场景处理 1. **PCIe 总线持续报错[^3]** ```bash # 禁用PCIe电源管理 echo "disable" | sudo tee /sys/bus/pci/devices/*/power/control ``` 2. **容器环境总线错误** 调整 cgroup 内存限制:`docker run --memory-swap="-1" ...` > **注意**:若日志中出现 `severity=Corrected`,表明系统已自动修复暂时性错误,但频繁出现需彻底排查硬件[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值