'strace'修复了挂起的进程

问题描述 投票:0回答:3

我有一个单线程 Unix 进程,它通过 TCP 与其他进程通信。

问题如下。当我启动进程时,它会挂起(没有忙循环),直到我杀死它。

有趣的是,一旦我将 strace 附加到它,它就会继续以预期的行为运行,就好像根本没有任何问题(总是可重现)。

这种行为的原因可能是什么? strace 对进程的状态有什么影响?


strace 改变行为的原因是,因为我们使用 openonload 有一个错误。一旦我们附加了 strace,堆栈就被移回内核,问题就消失了。

unix process rhel strace
3个回答
3
投票

许多年后,可能是完全不同的根本原因,这篇博文解释了为什么附加跟踪器可能会修复挂起的系统调用:https://ayende.com/blog/198849-C/production-postmortem-the-heisenbug -server?Key=1eeda567-02a8-4bbb-b90f-557523973233。看起来运行

strace
(或任何其他使用
ptrace
系统调用的工具)会导致“挂起”的系统调用返回(退出代码为
EINTR
)。

引用 ptrace 手册页

如果信号被发送到 a

,一些系统调用会返回 EINTR

tracee,但传递被示踪剂抑制了。 (这是很 典型操作:通常由调试器在每个 attach,以免引入虚假的 SIGSTOP)。从 Linux 开始 3.2.9,以下系统调用受到影响(这个列表是 可能不完整):epoll_wait(2),以及来自 inotify(7) 的 read(2) 文件描述符。这个错误的通常症状是当你 使用命令附加到静态进程

   strace -p <process-ID>

然后,而不是通常和预期的单行输出,例如

   restart_syscall(<... resuming interrupted call ...>_

   select(6, [5], NULL, [5], NULL_

('_'表示光标位置),你观察到不止一个 线。例如:

    clock_gettime(CLOCK_MONOTONIC, {15370, 690928118}) = 0
    epoll_wait(4,_

这里看不到的是进程被阻塞在 epoll_wait(2) 在 strace(1) 附加到它之前。附加 导致 epoll_wait(2) 返回用户空间并返回错误 EINTR。在这种特殊情况下,程序通过以下方式对 EINTR 作出反应 检查当前时间,然后执行 epoll_wait(2) 再次。 (不期望此类“杂散”EINTR 错误的程序 可能会在 strace(1) 附加时以意想不到的方式运行。)


0
投票

很可能 strace 输出只是减慢了进程,使死锁的可能性大大降低。我在使用 strace 之前看到过这种情况,或者在添加其他调试打印或调试调用时可能发生。

死锁最常见于多线程交互。但是在您的情况下,您有多个流程。如果 strace 每次都释放进程,那么我猜你打开套接字的方式或套接字上的握手方式就是挂起的。我认为在套接字上进行缓冲和阻塞可能会使您进入进程死锁状态。

类似的问题,但对于多线程进程,线程之间而不是单独进程之间的死锁:Using strace fixes hung memory issue

难以概括示例,尤其是不知道您的不同进程在做什么或者它们是否以某种方式共享资源?我会尝试 。 . .

  1. 一个应该被保护的对象/资源的例子:
    一个进程开始对对象进行更改(例如,将项目添加到列表/数据库表)
    另一个进程开始迭代列表/表。
    这些进程之一的危险迭代循环被混淆并且永远不会退出或做一些更糟糕的事情,比如写入无效内存。

  2. 对象/资源受互斥锁保护的示例
    具有两个资源问题的经典简单死锁。 ~ 比用餐哲学家简单
    一个线程/进程获取对象 A 上的互斥量,做一些工作。
    另一个线程/进程获取对象 B 上的互斥量,做一些工作。
    同一个线程/进程需要更新对象A,等待A的互斥量。
    原始线程/进程需要访问对象 B,等待 B 上的互斥量。
    。 . . . . . . . . . . . @. . . . . . . . . . .
    除了风声和风滚草吹过大地的声音外,一片寂静。
    僵局。


0
投票

我只遇到过一次这个问题,它与信号处理有关。它是单线程代码中竞争条件的来源之一。

© www.soinside.com 2019 - 2024. All rights reserved.