c++ - Log4cxx 日志语句挂起

标签 c++ multithreading log4cxx

我们有一个独立的 VC++ 应用程序,我们使用 log4cxx0.10.0 版本添加了日志记录。 应用程序将启动一个线程(用于一些耗时的操作),如果它花费的时间超过阈值时间,则主线程将使用 TerminateThread 方法终止线程。子线程函数也有一些日志记录打印。Log4CXX 配置了 1 MB 大小的滚动文件附加程序 5 个备份拷贝。日志记录在大多数情况下工作正常。但在某些情况下,主线程日志记录函数调用在杀死子线程后挂起,因此整个应用程序处于挂起状态。 应用程序的后续实例也挂起。我们获取了应用程序的完整故障转储并使用 WinDbg 进行了分析。

这是应用程序的调用栈

**00 ntdll!NtWaitForSingleObject+0xa
01 ntdll!RtlpWaitOnCriticalSection+0xe8
02 ntdll!RtlEnterCriticalSection+0xd1
03 log4cxx!log4cxx::filter::DenyAllFilter::decide+0x194
04 log4cxx!log4cxx::helpers::synchronized::synchronized+0x31
05 log4cxx!log4cxx::Logger::callAppenders+0x81
06 log4cxx!log4cxx::Logger::forcedLog+0xe5**
07 Test!CXX_LOG(int LOG_TYPE = 0n2, char * format = 0x00000001`3f2a2ad8 "Main thread pint...")+0x463 [d:\test\saf\test.cpp @ 2360]
08 test!TestFunction(int argc = 0n3, char ** argv = 0x00000001`3f2ae880, int level = 0n1)+0x586 [d:\test\saf\test.cpp @ 1634]
09 test!main(int argc = 0n4, char ** argv = 0x00000000`00282920)+0x1820 [d:\test\saf\test.cpp @ 2309]
0a test!__tmainCRTStartup(void)+0x13b [f:\dd\vctools\crt_bld\self_64_amd64\crt\src\crt0.c @ 278]
0b kernel32!BaseThreadInitThunk+0xd
0c ntdll!RtlUserThreadStart+0x1d

后续应用程序挂起锁定实例的文件和调用堆栈如下

**ntdll!ZwLockFile+0xa
KERNELBASE!LockFileEx+0xb2
kernel32!LockFileEx+0x1b
log4cxx!log4cxx::filter::DenyAllFilter::decide+0x2a89
log4cxx!log4cxx::helpers::DatagramPacket::setData+0x559c
log4cxx!log4cxx::helpers::FileOutputStream::write+0x82
log4cxx!log4cxx::rolling::RollingFileAppenderSkeleton::getTriggeringPolicy+0x1ca
log4cxx!log4cxx::helpers::OutputStreamWriter::write+0xbe
log4cxx!log4cxx::WriterAppender::subAppend+0x7c
log4cxx!log4cxx::rolling::RollingFileAppenderSkeleton::subAppend+0xd0
log4cxx!log4cxx::WriterAppender::append+0x31
log4cxx!log4cxx::AppenderSkeleton::doAppend+0x293
log4cxx!log4cxx::helpers::AppenderAttachableImpl::appendLoopOnAppenders+0x40
log4cxx!log4cxx::Logger::callAppenders+0xa3
log4cxx!log4cxx::Logger::forcedLog+0xe5**
test!CXX_LOG(int LOG_TYPE = 0n2, char * format = 0x00000001`3f2a3868 "Starting the application")+0x463
test!main(int argc = 0n4, char ** argv = 0x00000000`00162920)+0x1806
test!__tmainCRTStartup(void)+0x13b
kernel32!BaseThreadInitThunk+0xd
ntdll!RtlUserThreadStart+0x21

我们已经检查了函数“decide”,它与锁定无关。它只是返回一些常量值。我读过 LOG4CXX 是线程安全的。这个问题并不经常发生,因此我们没有以一致的方式重现的步骤。

kill掉子线程有什么需要注意的吗??

最佳答案

重新设计您的应用程序。 TerminateThread 本质上是隐式不安全的,因为线程使用的资源不会被释放。您刚刚在它持有锁时设法终止它,现在您的主线程正在尝试获取持有的锁。寻找一种不同的方式来终止线程。

这是堆栈跟踪中的锁:https://apache.googlesource.com/log4cxx/+/e3db59080a3506f0ed23e98cbcb2be58f0b15a20/src/main/cpp/logger.cpp#93

关于c++ - Log4cxx 日志语句挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23387676/

相关文章:

c++ - 如何从 C++ 中的文本文件中删除一行?

c++ - 将数字求和到 N 的最快算法

c++ - 使用 Ctrl-C 中断程序时,如何释放动态分配的空间?

c# - 可以在后台线程构建表单,然后在 UI 线程上显示

c++ - 用于 C++ 的进程安全日志库

c# - log4net 模式为没有完整路径的文件名提供了什么

c++ - 用户定义的文字、下划线和全局名称

c# - 为什么 Thread.Sleep 如此有害

multithreading - 如何从函数返回 JoinHandle?

logging - 与普通的 syslog() 相比,使用 log4cxx 有什么好处?