从 libc.so.6 调试停止的 write() 到 std::cout

Posted

技术标签:

【中文标题】从 libc.so.6 调试停止的 write() 到 std::cout【英文标题】:debugging stalled write() to std::cout from libc.so.6 【发布时间】:2014-11-29 22:38:56 【问题描述】:

我刚刚观察到二进制文件中发生了极其罕见的停顿。

附加 gdb 并切换到相关线程给出

(gdb) bt
#0  0x000000330a4db79d in write () from /lib64/libc.so.6
#1  0x000000330a471dd3 in _IO_new_file_write () from /lib64/libc.so.6
#2  0x000000330a473385 in _IO_new_do_write () from /lib64/libc.so.6
#3  0x000000330a4726df in _IO_new_file_overflow () from /lib64/libc.so.6
#4  0x000000330a46f437 in putc () from /lib64/libc.so.6
#5  0x00007f92d94864ea in sputc (__c=10 '\n', this=<optimized out>) at [..omitted..]/gcc-4.9.0-objdir/x86_64-linux-gnu/libstdc++-v3/include/streambuf:434
#6  std::ostream::put (this=0x3171f40 <std::cout>, __c=<optimized out>) at [..omitted..]/gcc-4.9.0-objdir/x86_64-linux-gnu/libstdc++-v3/include/bits/ostream.tcc:163

strace 给出了

Process 14702 attached - interrupt to quit
write(1, "[...some string...]", 31

它一直存在,写入 std::cout。我还应该收集哪些其他信息?应该如何深究?

编辑: 二进制文件由 python 系统调用,非常深入,它正在做

pipe = subprocess.Popen(
  command,
  shell=True,
  stdout=subprocess.PIPE,
  stderr=subprocess.STDOUT
)
output = pipe.stdout.read()
pipe.wait()

【问题讨论】:

如果cout 被重定向到管道并且目标程序在从管道读取之前进行分页或等待来自其他源的输入,这很常见。 感谢您的回复。二进制文件确实由 python 的子进程调用。有什么可以在 C++ 方面做的,还是应该在 python 方面工作? 这取决于正确的行为是什么。如果 C++ 进程的输出未被读取,应该怎么做?它应该等待吗?它应该不等待就继续吗? Python 子进程是否应该尽快读取 C++ 进程的所有输出?找出应该发生的事情并让它发生。 谢谢。进一步阅读后,python 一方最终成为了坏人。我想 C++ 端可以通过分离一个辅助线程来变得更安全。 【参考方案1】:

如果cout 被重定向到管道,那么如果管道另一端的进程读取速度不够快,则输出将阻塞。即使写入cout 块或管道的另一端是否必须从管道中读取,您需要决定是否应该构造 C++ 进程以继续前进。找出问题所在并修复它。

【讨论】:

以上是关于从 libc.so.6 调试停止的 write() 到 std::cout的主要内容,如果未能解决你的问题,请参考以下文章

如何使用调试版本的 libc

误删除libc.so.6补救办法

libc.so.6删除恢复

ubuntu下使用sudo命令误删libc.so.6后怎么才能恢复?

glibc升级GLIBC_2.14,一定不要mv libc.so.6 libc.so.6_bak……

Linux 误删libc.so.6