我可以排除SIGBUS是由于“小页面错误”引起的吗?(内核日志没有分配失败)

sou*_*edi 5 c linux x86-64 sigbus

动机

我正在尝试提高对Xwayland中SIGBUS错误的理解。自2018年2月20日左右以来,使用Fedora Linux的Xwayland 1.19.6-5.fc27.x86_64Linux内核已被多个Fedora Linux用户所见4.15.3-300.fc27.x86-64

遗憾的是,我没有内核“ segfault”日志消息(或SIGBUS等效消息)。Xwayland有一些毫无意义的代码,可以捕获致命信号。但是我可以siginfo通过调试coredump 看到,这似乎差不多。

定义

我了解当虚拟内存的页面在RAM中不可用并且必须从磁盘读取时会发生“主要页面错误”。我想我对ext4文件系统支持的页面特别感兴趣(例如,不能直接访问块设备)。

因此,当不需要磁盘访问时就是“较小的页面错误”。我认为差异是相当明确的,因为Linux公开了主要和次要页面错误的计数器。

我的问题

如果内核发送了一个SIGBUS程序,我想知道我是否通常应该认为这将是主要的页面错误。

根据核心转储和反汇编,程序在接收到SIGBUS时正在读取内存,而不是对其进行写入。中的错误地址在siginfo->si_addr映射的系统可执行文件内,该文件不能由用户写入,并且该地址似乎在当前文件长度的范围内。实际上,在调试coredump时,我已经从内存地址中读取了非常令人信服的值。似乎coredump生成过程阅读此地址没有困难:-(。

我也对排除“无效的地址对齐”情况(BUS_ADRALN)很有信心,因为siginfo->si_code是2,即BUS_ADRERR,“不存在的物理地址”。同样是因为我使用的是x86,在大多数情况下它允许未对齐的访问,并且陷阱不在任何SSE扩展指令中。

我考虑了内核在处理确定为“次要”的页面错误时通常负责的工作。我想小故障可能无法分配内存,从而引发SIGBUS。但是,我相信我会注意到这样的分配失败:

我有很多免费的交换操作可以将用户页面逐出,并且我没有注意到系统开始交换时通常发生的明显减速。崩溃发生在笔记本电脑从挂起状态变为ram状态后几秒钟,即使以约100MB / s的速度也不足以填充8GB的交换空间。我也没有看到可怕的内存不足(OOM)杀手出现在内核日志中,就像我期望的那样,如果内核未能成功分配页面框架或页面表。

还有其他可能性,一个轻微的页面错误可能会失败并导致SIGBUS?即,当在内核日志中查找错误时,有一些我不会注意到的原因吗?哪些会很快发作?

同样,多个核心转储将其显示为页面错误,这是通过从文件系统上的映射文件读取而触发的。

别有用心

我真的很想念一个小页面错误的情况。因为这令人恐惧的另一面是,我不明白这种SIGBUS可能是由硬页面错误方面引起的。从几个月前开始,我们中的一些用户有非常相似的错误。我的内核日志中没有IO错误。在正常操作期间,读取指示的文件时没有IO错误。运行rpm --verify --all或在HDD上运行扩展的SMART测试时,我没有任何错误。不幸的是,我似乎很少有嫌疑犯。在最近的怀疑我有一个内核升级,显然我想排除它;日期并不能完全证明这一点,但是还不能完全排除。日期最近的是今年的微代码更新。这似乎更难确定。

轻微页面错误的已知原因

  1. 从逻辑上讲,当实现MAP_PRIVATE映射的写时复制时,听起来好像发生了轻微的页面错误。
  2. 它还应该包括/ dev / zero或MAP_ANONYMOUS上的读取错误,假设内核没有它们实现为读取共享的零页,并且没有实现为立即为整个映射分配页的实现。
  3. 但更一般而言,它可以是对页面的任何首次访问。这是因为似乎通常是按需填充用于内存映射的页表。(这将由页面错误来完成,并且如果文件页面已经在高速缓存中,则只会是次要的页面错误)。

    MAP_NONBLOCK(自Linux 2.5.46起)

    该标志仅与MAP_POPULATE结合使用才有意义。不要执行预读:仅为RAM中已经存在的页面创建页表条目。从Linux 2.6.23开始,此标志导致MAP_POPULATE不执行任何操作。有一天,combinina?可以重新实现MAP_POPULATE和MAP_NONBLOCK的功能。


编辑:详细摘录以上的进一步摘录

评论者要求提供更具体的细节,以澄清错误的地址和说明。初始链接https://bugzilla.redhat.com/show_bug.cgi?id=1557682中有很多节选

故障根据错误链接中的描述而变化。这是最近事例的摘录。

$ gdb 2018-03-21.core
...
Core was generated by `/usr/bin/Xwayland :0 -rootless -terminate -core -listen 4 -listen 5 -displayfd'.
Program terminated with signal SIGBUS, Bus error.
#0  _dl_fixup (l=0x7fc0be2e0130, reloc_arg=203) at ../elf/dl-runtime.c:73
73    const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
[Current thread is 1 (Thread 0x7fc0be29fa80 (LWP 1918))]
(gdb) p $_siginfo.si_signum
$1 = 7
(gdb) p $_siginfo.si_code
$2 = 2
(gdb) p $_siginfo._sifields._sigfault.si_addr
$3 = (void *) 0x41bd80
(gdb) disassemble
Dump of assembler code for function _dl_fixup:
   0x00007fc0be0c8bd0 <+0>: push   %rbx
   0x00007fc0be0c8bd1 <+1>: mov    %rdi,%r10
   0x00007fc0be0c8bd4 <+4>: mov    %esi,%esi
   0x00007fc0be0c8bd6 <+6>: lea    (%rsi,%rsi,2),%rdx
   0x00007fc0be0c8bda <+10>:    sub    $0x10,%rsp
   0x00007fc0be0c8bde <+14>:    mov    0x68(%rdi),%rax
   0x00007fc0be0c8be2 <+18>:    mov    0x8(%rax),%rdi
   0x00007fc0be0c8be6 <+22>:    mov    0xf8(%r10),%rax
   0x00007fc0be0c8bed <+29>:    mov    0x8(%rax),%rax
   0x00007fc0be0c8bf1 <+33>:    lea    (%rax,%rdx,8),%r8
   0x00007fc0be0c8bf5 <+37>:    mov    0x70(%r10),%rax
=> 0x00007fc0be0c8bf9 <+41>:    mov    0x8(%r8),%rcx
(gdb) p/x $r8
$4 = 0x41bd78
(gdb) p/x $r8 + 8
$5 = 0x41bd80
Run Code Online (Sandbox Code Playgroud)

请注意,此指令将reloc->r_info按照突出显示的源代码行获取值。

(gdb) p reloc
$6 = (const Elf64_Rela * const) 0x41bd78
(gdb) p &reloc->r_info
$7 = (Elf64_Xword *) 0x41bd80
(gdb) p *reloc
$8 = {r_offset = 8443504, r_info = 936302870535, r_addend = 0}
Run Code Online (Sandbox Code Playgroud)

错误地址位于下面的文本映射中(来自maps捕获的文件abrtd):

00400000-0060b000 r-xp 00000000 fd:00 1708508                            /usr/bin/Xwayland
0080a000-0080d000 r--p 0020a000 fd:00 1708508                            /usr/bin/Xwayland
0080d000-00817000 rw-p 0020d000 fd:00 1708508                            /usr/bin/Xwayland

$ size -x /usr/bin/Xwayland
   text    data     bss     dec     hex filename
0x209ffb     0xbe9d 0x1f3e0 2314872  235278 /usr/bin/Xwayland
Run Code Online (Sandbox Code Playgroud)

sou*_*edi 1

感谢各位的支持。这确实是一个短暂的 IO 错误。看来 SIGBUS 读取故障路径不一定会在内核日志中记录任何内容,这与我习惯看到的 IO 错误的情况不同。

https://marc.info/?l=linux-ide&m=152232081917215&w=2

v4.15 挂起/恢复时出现间歇性错误

对于任何等待其他节目在 SATA LPM 上发布的人...

我发现了至少在同一区域的东西。两天前它在我的系统上触发了一次 fsck。有证据表明许多其他机器上也发生过这种情况。我觉得这足以给你一个提醒:)。

我检查了一下,似乎在运行时没有启用 LPM,即使在使用电池运行时也是如此。我的错误全部发生在挂起/恢复上,所以也许该行为同时发生了改变?

它并不总是显示在内核日志中。我首先注意到的是一个神秘的 SIGBUS,它在从挂起恢复时杀死了 Xwayland(从而杀死了整个 Gnome 会话)。让我惊讶的是,这个 SIGBUS 可以发生,而不会留下任何像我习惯在内核日志中看到的读取错误那样的东西!

我的核心转储显示 SIGBUS 故障地址是 Xwayland 程序代码内读取的指令。回溯在同一调用链上各不相同 - 共同点是它们始终位于函数的第一条指令处。我假设它根据当前不在核心的页面而变化,因此触发失败的读取请求。

沿着同一个调用链,有数百个来自其他用户的回溯,自动报告给 Fedora,看起来是一样的。至少到目前为止,我们还没有找到更合理的说法。我承认 Xwayland 如此突出很有趣,而且我在其他进程中没有被 SIGBUS 淹没,但我支持这个分析。

这些崩溃是在 Fedora 升级到内核 v4.15 后 24 小时内开始的。

Xwayland SIGBUS 的 Fedora 错误: https://bugzilla.redhat.com/show_bug.cgi? id=1553979

我的重复错误一直在发送令人困惑的评论: https://bugzilla.redhat.com/show_bug.cgi?id=1557682

众多崩溃报告桶中最早且最大的一个:

EXT4 文件系统错误:

Mar 27 11:28:30 alan-laptop kernel: PM: suspend exit
...
Mar 27 11:28:30 alan-laptop kernel: EXT4-fs error (device dm-2):  ext4_find_entry:1436: inode #5514052: comm thunderbird: reading directory lblock 0
Mar 27 11:28:30 alan-laptop kernel: Buffer I/O error on dev dm-2, logical block 0, lost sync page write
(this marked the FS as needing fsck on next boot)
Run Code Online (Sandbox Code Playgroud)

更常见的是,它会记录这些交换错误:

Mar 02 18:47:03 alan-laptop kernel: Restarting tasks ...
Mar 02 18:47:03 alan-laptop kernel: Read-error on swap-device (253:1:836184)
Mar 02 18:47:06 alan-laptop kernel: Read-error on swap-device (253:1:580280)
Run Code Online (Sandbox Code Playgroud)

我的笔记本电脑 LPM 状态,即使在断开交流电源后也是如此:

$ head /sys/class/scsi_host/host*/link_power_management_policy
==> /sys/class/scsi_host/host0/link_power_management_policy <==
max_performance

==> /sys/class/scsi_host/host1/link_power_management_policy <==
max_performance
Run Code Online (Sandbox Code Playgroud)

我的笔记本电脑是 Dell Latitude E5450。CPU是i5-5300U(Broadwell)。