【问题标题】:Hung processes resume if attached to strace如果附加到 strace,挂起的进程将恢复
【发布时间】:2014-02-19 13:28:25
【问题描述】:

我有一个使用 TCP 套接字用 C 语言编写的网络程序。有时客户端程序永远挂起等待来自服务器的输入。具体来说,客户端挂起在 fd 上设置的 select() 调用,该 fd 旨在读取服务器发送的字符。

我正在使用 strace 来了解进程卡在哪里。但是,有时当我将挂起的客户端进程附加到 strace 时,它​​会立即恢复执行并正确退出。并非所有挂起的进程都表现出这种行为,即使我将它们附加到 strace,某些进程也会卡在 select() 中。但是大多数进程在附加到 strace 时会恢复执行。

我很好奇是什么导致进程在附加到 strace 时恢复。它可能会给我一些线索,让我知道为什么客户端进程会挂起。

有什么想法吗?是什么导致挂起的进程在附加到 strace 时恢复执行?

更新:

这是 strace 在挂起进程上的输出。

> sudo strace -p 25645
Process 25645 attached - interrupt to quit
--- SIGSTOP (Stopped (signal)) @ 0 (0) ---
--- SIGSTOP (Stopped (signal)) @ 0 (0) ---
[ Process PID=25645 runs in 32 bit mode. ]
select(6, [3 5], NULL, NULL, NULL)      = 2 (in [3 5])
read(5, "\0", 8192)                     = 1
write(2, "", 0)                         = 0
read(3, "====Setup set_oldtempbehaio"..., 8192) = 555
write(1, "====Setup set_oldtempbehaio"..., 555) = 555
select(6, [3 5], NULL, NULL, NULL)      = 2 (in [3 5])
read(5, "", 8192)                       = 0
read(3, "", 8192)                       = 0
close(5)                                = 0
kill(25652, SIGKILL)                    = 0
exit_group(0)                           = ?
Process 25645 detached

_

> sudo strace -p 14462
Process 14462 attached - interrupt to quit
[ Process PID=14462 runs in 32 bit mode. ]
read(0, 0xff85fdbc, 8192)               = -1 EIO (Input/output error)
shutdown(3, 1 /* send */)               = 0
exit_group(0)                           = ?

_

> sudo strace -p 7517
Process 7517 attached - interrupt to quit
--- SIGSTOP (Stopped (signal)) @ 0 (0) ---
--- SIGSTOP (Stopped (signal)) @ 0 (0) ---
[ Process PID=7517 runs in 32 bit mode. ]
connect(3, {sa_family=AF_INET, sin_port=htons(300), sin_addr=inet_addr("100.64.220.98")}, 16) = -1 ETIMEDOUT (Connection timed out)
close(3)                                = 0
dup(2)                                  = 3
fcntl64(3, F_GETFL)                     = 0x1 (flags O_WRONLY)
close(3)                                = 0
write(2, "dsd13: Connection timed out\n", 30) = 30
write(2, "Error code : 110\n", 17)      = 17
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
exit_group(1)                           = ?
Process 7517 detached

不仅是 select(),而且(同一程序的)进程在我将它们附加到 strace 之前会卡在各种系统调用中。他们在附加到 strace 后突然恢复。如果我不将它们附加到 strace,它们就会永远挂在那里。

更新 2:

我了解到 strace 可以启动以前停止的进程(T 状态的进程)。现在我试图了解为什么这些过程会进入“T”状态,原因是什么。这是/proc//状态信息:

> cat /proc/12554/status
Name:   someone
State:  T (stopped)
SleepAVG:       88%
Tgid:   12554
Pid:    12554
PPid:   9754
TracerPid:      0
Uid:    5000    5000    5000    5000
Gid:    48986   48986   48986   48986
FDSize: 256
Groups: 9149 48986
VmPeak:     1992 kB
VmSize:     1964 kB
VmLck:         0 kB
VmHWM:       608 kB
VmRSS:       608 kB
VmData:      156 kB
VmStk:        20 kB
VmExe:        16 kB
VmLib:      1744 kB
VmPTE:        20 kB
Threads:        1
SigQ:   54/73728
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000006
SigCgt: 0000000000004000
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
Cpus_allowed:   00000000,00000000,00000000,0000000f
Mems_allowed:   00000000,00000001

【问题讨论】:

  • 看起来T状态的进程在附加到strace时会开始执行。如果在执行时退出 strace 会话,进程将再次进入 T 状态。

标签: sockets linux-kernel gdb strace ptrace


【解决方案1】:

strace 使用ptraceptrace man page 有这个:

Since attaching sends SIGSTOP and the tracer usually suppresses it,
this may cause a stray EINTR return from the currently executing system
call in the tracee, as described in the "Signal injection and
suppression" section.

你看到select返回EINTR了吗?

【讨论】:

  • 不,select() 正确返回。我用 strace 输出更新了我的问题。
  • 我看到一些其他进程卡在不同的地方(connect()、read()...等)。令人惊讶的是,一旦我将所有这些进程附加到 strace,它们就会恢复执行。其中唯一的共同点是它们从一个月开始就一直在运行(实际上是挂起)。 Linux 内核会保留不活动的进程(无 I/O)并且从不恢复它们吗?
  • 我尝试提高 NICE 的优先级。但是 NICE 对它们没有任何影响,只有 strace 能以某种方式发挥作用。
  • 我查看了所有这些挂起进程的进程状态。其中一些处于 S+ 状态,一些处于 T 状态。在附加到 strace 时恢复执行的是处于“T”状态的那些。 kill -SIGCONT <pid> 也会以“T”状态启动那些挂起的进程。但是,我不清楚是什么让他们进入“T”状态。内核会在等待很长时间后将进程发送到“T”状态吗?没有人明确地发出SIGSTOP 信号以将进程发送到“T”状态?
  • 'T' 状态表示停止。它可能是由跟踪它的另一个进程引起的(在这种情况下,/proc/pid/status 可能显示非零 TracerPid)或者因为它被发送了 SIGTSTP(通过键入 control-Z),或者发送了 SIGSTOP,或者得到了 SIGTTOU 或 SIGTTIN如果它在后台尝试在终端上进行输出或输入。我不认为仅仅因为一个进程一直在等待而出现“T”状态。你的select 是只涉及网络套接字,还是也涉及终端设备?
猜你喜欢
  • 2013-12-14
  • 2011-07-22
  • 2023-04-05
  • 1970-01-01
  • 2014-02-21
  • 2012-05-20
  • 2011-07-09
  • 2014-06-17
  • 1970-01-01
相关资源
最近更新 更多