linux - 读取返回 ERESTARTSYS 后被 SIGHUP 杀死的进程

标签 linux debugging strace

我们有一些应用程序调用连接到 Oracle 数据库的 PHP 脚本来执行某些操作。 :) 有时效果不佳。

我们现在从一开始就通过 strace 运行 PHP 部分。

这是一切正常时的样子(一切正常,数据库连接已建立,查询已执行,数据库再次断开连接等):

10:30:17.935486 connect(8, {sa_family=AF_INET, sin_port=htons(1521), sin_addr=inet_addr("10.1.1.55")}, 16) = -1 EINPROGRESS (Operation now in progress)
10:30:17.935546 times(NULL)             = 2908590046
10:30:17.935569 brk(0xda4000)           = 0xda4000
10:30:17.935594 poll([{fd=8, events=POLLOUT}], 1, 60000) = 1 ([{fd=8, revents=POLLOUT}])
10:30:17.940338 getsockopt(8, SOL_SOCKET, SO_ERROR, [519270883345301504], [4]) = 0
10:30:17.940368 fcntl(8, F_GETFL)       = 0x802 (flags O_RDWR|O_NONBLOCK)
10:30:17.940388 fcntl(8, F_SETFL, O_RDWR) = 0
10:30:17.940408 getsockname(8, {sa_family=AF_INET, sin_port=htons(62498), sin_addr=inet_addr("192.168.22.30")}, [16]) = 0
10:30:17.940437 getsockopt(8, SOL_SOCKET, SO_SNDBUF, [-4193870156763480064], [4]) = 0
10:30:17.940458 getsockopt(8, SOL_SOCKET, SO_RCVBUF, [-4193870156763409068], [4]) = 0
10:30:17.940483 setsockopt(8, SOL_TCP, TCP_NODELAY, [1], 4) = 0
10:30:17.940506 fcntl(8, F_SETFD, FD_CLOEXEC) = 0
10:30:17.940652 rt_sigaction(SIGPIPE, {0x1, ~[ILL ABRT BUS FPE SEGV USR2 TERM XCPU XFSZ SYS RTMIN RT_1], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x7f7198b2b920}, {0x1, [PIPE], SA_RESTORER|SA_RESTART, 0x7f7198b2b920}, 8) = 0
10:30:17.940725 write(8, "\x00\xe8\x00\x00\x01\x00\x00\x00\x01\x3b\x01\x2c\x0c\x41\x20\x00\xff\xff\x7f\x08\x00\x00\x01\x00\x00\xa2\x00\x46\x00\x00\x08\x00"..., 232) = 232
10:30:17.940781 read(8, "\x00\x08\x00\x00\x0b\x00\x00\x00", 8208) = 8
10:30:17.974177 write(8, "\x00\xe8\x00\x00\x01\x00\x00\x00\x01\x3b\x01\x2c\x0c\x41\x20\x00\xff\xff\x7f\x08\x00\x00\x01\x00\x00\xa2\x00\x46\x00\x00\x08\x00"..., 232) = 232
10:30:17.974247 read(8, "\x00\x29\x00\x00\x02\x00\x00\x00\x01\x3b\x0c\x41\x00\x00\x00\x00\x01\x00\x00\x00\x00\x29\x51\x41\x00\x00\x00\x00\x00\x00\x00\x00"..., 8208) = 41
10:30:17.976465 write(8, "\x00\x00\x00\xa4\x06\x20\x00\x00\x00\x00\xde\xad\xbe\xef\x00\x9a\x00\x00\x00\x00\x00\x04\x00\x00\x04\x00\x03\x00\x00\x00\x00\x00"..., 164) = 164
....

这是当一切都无法正常工作时的样子:

10:23:24.888170 connect(8, {sa_family=AF_INET, sin_port=htons(1521), sin_addr=inet_addr("10.1.1.55")}, 16) = -1 EINPROGRESS (Operation now in progress)
10:23:24.888241 times(NULL)             = 2908548738
10:23:24.888263 brk(0xda4000)           = 0xda4000
10:23:24.888287 poll([{fd=8, events=POLLOUT}], 1, 60000) = 1 ([{fd=8, revents=POLLOUT}])
10:23:24.889769 getsockopt(8, SOL_SOCKET, SO_ERROR, [519270883345301504], [4]) = 0
10:23:24.889807 fcntl(8, F_GETFL)       = 0x802 (flags O_RDWR|O_NONBLOCK)
10:23:24.889827 fcntl(8, F_SETFL, O_RDWR) = 0
10:23:24.889845 getsockname(8, {sa_family=AF_INET, sin_port=htons(62473), sin_addr=inet_addr("192.168.22.30")}, [16]) = 0
10:23:24.889873 getsockopt(8, SOL_SOCKET, SO_SNDBUF, [-8374476973480591360], [4]) = 0
10:23:24.889892 getsockopt(8, SOL_SOCKET, SO_RCVBUF, [-8374476973480520364], [4]) = 0
10:23:24.889915 setsockopt(8, SOL_TCP, TCP_NODELAY, [1], 4) = 0
10:23:24.889936 fcntl(8, F_SETFD, FD_CLOEXEC) = 0
10:23:24.890062 rt_sigaction(SIGPIPE, {0x1, ~[ILL ABRT BUS FPE SEGV USR2 TERM XCPU XFSZ SYS RTMIN RT_1], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x7f2ee24b4920}, {0x1, [PIPE], SA_
RESTORER|SA_RESTART, 0x7f2ee24b4920}, 8) = 0
10:23:24.890129 write(8, "\x00\xe8\x00\x00\x01\x00\x00\x00\x01\x3b\x01\x2c\x0c\x41\x20\x00\xff\xff\x7f\x08\x00\x00\x01\x00\x00\xa2\x00\x46\x00\x00\x08\x00"..., 232) = 232
10:23:24.890186 read(8, 0xd705a6, 8208) = ? ERESTARTSYS (To be restarted)
10:23:24.907853 --- SIGHUP (Hangup) @ 0 (0) ---
10:23:24.908708 +++ killed by SIGHUP +++

这种情况有时会发生,应用程序(或至少是 PHP 脚本和与数据库的连接)会被终止。这很糟糕。

  • 您如何看待上述趋势?
  • 我们能看出谁被谁杀死了吗?
  • 为什么 read() 会返回 ERESTARTSYS?
  • SIGHUP (Hangup) @0 (0) 究竟告诉我们什么?

最佳答案

您的进程收到了一个 SIGHUP,这导致了正常的退出操作。

不知道是谁干的。尝试更新版本的 strace。据我所知,从 2011 年一直回到 4.6 版,它应该会显示更多信息。您使用的 strace 版本是 2011 年之前的版本,@0 (0) 提供收到信号时进程的 PC 以及与来自 siginfo_t< 的信号关联的地址。两者都不会告诉您有关此问题的任何信息。

较新的版本将提供如下内容:

--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=25064, si_uid=1000} ---
--- SIGHUP {si_signo=SIGHUP, si_code=SI_KERNEL} ---

这首先是发送 SIGHUP 的另一个进程。第二个是由于某些事件而自动发送的。

后者可能发生在进程的控制终端关闭或 session 领导者因为其终端关闭而退出时。如果您确定是内核发送信号,那么我会在您的进程运行时查看它并检查 ps 输出中的“sid”和“tty”列。这将告诉您负责发送 SIGHUP 的 session 负责人和终端。也许有时您的脚本有一个控制终端,有时却没有?

session 负责人通常是启动脚本的父进程,或者该进程的父进程,或者那个进程的父进程等。查看 ps 输出和“sid”会告诉您。如果领导进程退出并有一个控制终端,它下面的所有东西都会收到一个 SIGHUP。解决这个问题的方法是让领导者在 PHP 进程完成之前不退出,或者在某个时候与该 session 或终端分离。通常守护进程或服务器进程不应与终端相关联。参见 daemon()setsid()

关于linux - 读取返回 ERESTARTSYS 后被 SIGHUP 杀死的进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41891406/

相关文章:

ssh - autossh 失败,退出状态为 1,并且没有错误消息

c++ - 在 Linux 上为 OpenGL 4.2 设置开发环境(无法获取 gl.h)

linux - Bash 脚本输出到控制台和文件

java - 程序如何让Lua(或python)解释器执行程序提供的语句?

c - 在 Xcode 4 中运行外部可执行文件以将其用作调试器

c - ptrace在用户级还是内核级工作?

linux - svn 取消删除和更改文件夹和文件的状态

javascript - Google 地球插件点击时崩溃

debugging - 什么是调试器以及它如何帮助我诊断问题?

linux - 什么可以使程序在 `strace` 内表现不同?