【问题标题】:Freeze on __write_nocancel冻结 __write_nocancel
【发布时间】:2012-07-04 20:28:37
【问题描述】:

所以我有一个相当充实的程序,它偶尔会冻结。
该程序使用 Qt、开放场景图和谷歌日志。这种冻结发生在谷歌日志中的打印中间。该程序本身正在打印大量调试信息。我能够通过 gdb-server 连接到程序,这是堆栈跟踪:

#0  0x000000397ac0e030 in __write_nocancel () at ../sysdeps/unix/syscall-template.S:82
#1  0x00007f5eecb74aeb in google::LogMessage::SendToLog() () from /lib64/libglog.so.0
#2  0x00007f5eecb71fc7 in google::LogMessage::Flush() () from /lib64/libglog.so.0
#3  0x00007f5eecb721a9 in google::LogMessage::~LogMessage() () from /lib64/libglog.so.0
#4  0x00000000004874a6 in LSDB::process (this=0x242d918, lsp=0x25f9200, circuit=0x24c7af0) at ../src/model/trill/LSDB.cpp:481
#5  0x00000000004a0f6f in Circuit::rx (this=0x24c7af0, eth=0x246fdf0) at ../src/model/trill/Circuit.cpp:355
#6  0x000000000045c950 in Circuit::qt_static_metacall (_o=0x24c7af0, _c=QMetaObject::InvokeMetaMethod, _id=0, _a=0x7fffaade95a0)
    at ../src/model/trill/Circuit.moc.cpp:55
#7  0x000000398798cb9f in QMetaObject::activate (sender=0x2470140, m=<optimized out>, local_signal_index=<optimized out>, argv=0x7fffaade95a0)
    at kernel/qobject.cpp:3547
#8  0x0000000000459610 in FramePublisher::subscription (this=0x2470140, _t1=0x246fdf0) at ../src/model/system/FramePublisher.moc.cpp:98
#9  0x000000000047c0d6 in FramePublisher::rx (this=0x2470140, frame=0x246fdf0) at ../src/model/system/FramePublisher.hpp:21
#10 0x000000000047bedb in EthernetPort::rx (this=0x246d7a0, frame=0x25a4180) at ../src/model/system/EthernetPort.cpp:81
#11 0x000000000045a208 in EthernetPort::qt_static_metacall (_o=0x246d7a0, _c=QMetaObject::InvokeMetaMethod, _id=1, _a=0x7fffaade9810)
    at ../src/model/system/EthernetPort.moc.cpp:51
#12 0x000000398798cb9f in QMetaObject::activate (sender=0x246d7a0, m=<optimized out>, local_signal_index=<optimized out>, argv=0x7fffaade9810)
    at kernel/qobject.cpp:3547
#13 0x0000000000459ddc in Port::rx (this=0x246d7a0, _t1=0x25a4180) at ../src/model/system/Port.moc.cpp:110
#14 0x00000000004803a6 in Port::inject (this=0x246d7a0, frame=0x25a4180) at ../src/model/system/Port.cpp:25

...

注意冻结本身发生在__write_nocancel。只有一个线程在运行...

(gdb) 信息线程 ID 目标 ID 帧
* 1 线程 21507 0x000000397ac0e030 在 ../sysdeps/unix/syscall-template.S:82 的 __write_nocancel () 中

关于导致冻结的原因有什么想法吗?让我知道其他信息可能会有所帮助。

【问题讨论】:

  • 所以我使用 GLOG 和 GLOG_logtostderr=1 这意味着它将日志消息写入标准错误。从文档中它说,当您设置了该标志时,它会跳过写入文件。 google-glog.googlecode.com/svn/trunk/doc/glog.html我没有看到任何应该导致此问题的 valgrind 问题。
  • 你有没有发现是什么原因造成的?
  • 不,我没有。如果有人确实知道出了什么问题,我会很高兴...
  • 经过进一步调查,这似乎与打印速度过快有关......我还注意到当我杀死 -9 时终端没有恢复进程。

标签: c++ qt unix io glog


【解决方案1】:

您说输出正在写入 stderr。如果 stderr 没有被单独的进程持续读取,则 I/O 缓冲区可能已满,因此它在写入更多内容之前等待 stderr 被读取。

如果进程 A 正在写入 stderr 而进程 B 通常从 stderr 读取但当前正在等待进程 A,这可能会导致死锁。在您的情况下,如果对 stderr 的写入太大,它只会导致死锁,因为较小的写入会立即成功并释放进程 A,从而释放进程 B 以从 stderr 读取。

这是我的一些猜测,但总的来说,我认为您的问题是您正在等待写入完整的缓冲区。

【讨论】:

  • 好吧,在这种情况下,进程 B 是终端,所以它不应该在我的进程中等待我能想象到的任何事情。如果写入缓冲区已填满,则该进程应该会产生,并且终端将有一些时间来处理它需要的内容。不过感谢您的想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-24
  • 2011-10-24
  • 2015-11-17
  • 2013-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多