【问题标题】:Trouble understanding strace of a process无法理解进程的 strace
【发布时间】:2016-12-15 05:46:52
【问题描述】:

我有一个作为守护进程运行的 perl 脚本。它每 10 秒访问一次数据库,如果队列中有任何作业,它会生成一个单独的 shell 来执行单个作业。但是脚本经常无法从数据库中获取作业。

理想情况下,应该像这样调用 DB

read(3, "\3def\3job\rqueueb\7JobTy"..., 55) = 55
read(3, ";\0\0\6", 4)                   = 4

下面是这个守护进程/进程的 strace。是在等什么吗?感谢您的帮助。

pipe([6, 7])                            = 0
pipe([8, 9])                            = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0) = 31858
close(9)                                = 0
close(7)                                = 0
read(8, "", 4)                          = 0
close(8)                                = 0
fcntl64(6, F_GETFL)                     = 0 (flags O_RDONLY)
fstat64(6, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xfffffffff7783000
_llseek(6, 0, 0xffd4e540, SEEK_CUR)     = -1 ESPIPE (Illegal seek)
fstat64(6, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
read(6, "", 4096)                       = 0
close(6)                                = 0
munmap(0xf7783000, 4096)                = 0
rt_sigaction(SIGHUP, {SIG_IGN, [], 0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGINT, {SIG_IGN, [], 0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {SIG_IGN, [], 0}, {SIG_DFL, [], 0}, 8) = 0
waitpid(31858, 0xffd4e670, 0)           = -1 ECHILD (No child processes)
rt_sigaction(SIGHUP, {SIG_DFL, [], 0}, NULL, 8) = 0
rt_sigaction(SIGINT, {SIG_DFL, [], 0}, NULL, 8) = 0
rt_sigaction(SIGQUIT, {SIG_DFL, [], 0}, NULL, 8) = 0

这会立即重复(至少)两次。

【问题讨论】:

  • 我认为没有源代码的 strace 没有任何价值。再说一次,如果来源是 Perl,我怀疑 strace 是否会有所帮助。您需要在调试器中运行您的 Perl 并设置一个断点,在该断点处检测到没有可用的作业,并等到它在您知道作业可用的情况下触发。然后查看程序的变量以了解发生了什么。
  • 或者,在您认为有用的地方添加打印语句的 Perl 脚本。或者,在此处发布脚本 - 简化为仍然存在该问题的最小版本。这(strace)对于不了解您的脚本的人几乎没有用处。
  • _llseek 似乎是个嫌疑犯。需要查看脚本以了解发生了什么。
  • 我怀疑 llseek 是个问题。它寻求当前位置,可能是为了清除缓冲区,但我敢打赌它在管道上失败并不重要。

标签: linux database perl shell strace


【解决方案1】:

这会创建一个子进程 (clone),并尝试从中获取数据 (read 6)。孩子关闭了管道,因此读取返回 EOF (0)。这被认为是孩子已经退出的迹象,因此它试图收割孩子(waitpid)。这会失败 (-1),这意味着必须将 $SIG{CHLD} 设置为 IGNORE。该状态可能很有用。

8/9 管道的存在表明孩子将调用exec。管道用于通知父处理文件句柄或调用exec 时出错。子进程会将9 设置为close-on-exec,因此从该管道接收到没有任何数据的EOF(就像这里的情况一样)表明exec 是成功的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 2023-03-25
    • 2013-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多