gcc 4.7.1 C++ 静态局部初始化挂起
gcc 4.7.1 C++ static local initialization hangs
... 并在线程被信号踢出时恢复。没有可用的核心转储或堆栈跟踪。
有没有人以前见过这种行为并且能够对任何已知的 gcc/glibc 错误进行注释?
在 RHEL 5.5 Westmere 上见过一次,在 RHEL 6.5 Sandybridge 上见过一次。我第一次做 pstack,它是在 cxa_guard_acquire 本地静态初始化生成的守卫中,运行 pstack (=attaching/detaching gdb) 当时恢复了线程。
这似乎是 this commit 修复的错误的表现。有bug的版本可以(最小复现需要三个线程)取消订阅所有等待静态初始化完成的线程从“唤醒调用”,所以触发初始化的线程在完成时不会唤醒其他线程。
cxa_guard_acquire 的 FSM 有四种可能的状态:
- 未初始化
- 正在初始化
- 初始化+等待
- 已初始化
命中局部静态变量的第一个线程将机器切换到 "initializing",在初始化完成之前命中它的后续线程将其切换到 "initializing + waiting" 并阻塞在 futex 上。初始化完成后,如果初始化结束时状态为 "initializing + waiting",则初始化线程会唤醒所有阻塞在 futex 上的人。一个错误可能会导致“初始化 + 等待重置回 "initializing"。
... 并在线程被信号踢出时恢复。没有可用的核心转储或堆栈跟踪。
有没有人以前见过这种行为并且能够对任何已知的 gcc/glibc 错误进行注释?
在 RHEL 5.5 Westmere 上见过一次,在 RHEL 6.5 Sandybridge 上见过一次。我第一次做 pstack,它是在 cxa_guard_acquire 本地静态初始化生成的守卫中,运行 pstack (=attaching/detaching gdb) 当时恢复了线程。
这似乎是 this commit 修复的错误的表现。有bug的版本可以(最小复现需要三个线程)取消订阅所有等待静态初始化完成的线程从“唤醒调用”,所以触发初始化的线程在完成时不会唤醒其他线程。
cxa_guard_acquire 的 FSM 有四种可能的状态:
- 未初始化
- 正在初始化
- 初始化+等待
- 已初始化
命中局部静态变量的第一个线程将机器切换到 "initializing",在初始化完成之前命中它的后续线程将其切换到 "initializing + waiting" 并阻塞在 futex 上。初始化完成后,如果初始化结束时状态为 "initializing + waiting",则初始化线程会唤醒所有阻塞在 futex 上的人。一个错误可能会导致“初始化 + 等待重置回 "initializing"。