如何保护日志免受应用程序崩溃?

时间:2021-09-07 22:00:33

I've created a simple logger which, well, logs everything of importance into a text file. I'm using std::ofstream but there's a problem - when the program doesn't close the file (call std::ofstream::close()) for whatever reason (like crash), the created log is actually empty (0 size). And since the log is most useful in exceptional situations (when something goes wrong) - you see the problem.

我创建了一个简单的记录器,它将重要的一切记录到文本文件中。我正在使用std :: ofstream但是有一个问题 - 当程序没有因任何原因(如崩溃)关闭文件(调用std :: ofstream :: close())时,创建的日志实际上是空的(0尺寸)。并且由于日志在特殊情况下(当出现问题时)最有用 - 您会看到问题。

Is there any way to protect my log from that? I could try closing the file after writing every couple of lines and using append - but that still doesn't protect me from the situation when the program crashes in the middle of logging/before closing the file. Is there any solution or am I just doomed?

有没有办法保护我的日志?我可以尝试在写完每一行并使用append后关闭文件 - 但是这仍然不能保护我免受程序在记录/关闭文件之前崩溃的情况。有没有解决方案还是我注定要失败?

2 个解决方案

#1


3  

You should employ flush method, it is there to precisely solve problems like the one you're facing.

您应该使用flush方法,它可以精确地解决您所面临的问题。

There is another approach which can be considered more safe, but requires substantially more effort to implement and test. The approach boils down to what is known as inter-process communication (IPC). In brief, you could implement your logger as a separate logger application which would communicate with your target application by means of specific protocol (interface). You can develop such protocol by yourself or employ one of the existing ones (which are usually very generic, i.e. general purpose). As a result, if your target application crashes, it doesn't drag logger application with it, and therefore logger can safely finish its job.

还有另一种方法可以被认为更安全,但需要更多的努力来实施和测试。该方法归结为所谓的进程间通信(IPC)。简而言之,您可以将记录器实现为单独的记录器应用程序,该应用程序将通过特定协议(接口)与目标应用程序进行通信。您可以自己开发此类协议,也可以使用现有协议(通常非常通用,即通用)。因此,如果您的目标应用程序崩溃,它不会随之拖动记录器应用程序,因此记录器可以安全地完成其工作。

That approach is usually used by some huge, complex, and safety-critical systems. However, I guess that in your case this is definitely an overkill and bare flush() after each append is more than enough.

这种方法通常由一些庞大,复杂且安全关键的系统使用。但是,我想在你的情况下,这肯定是一个矫枉过正,并且在每次附加后勉强刷新()。

#2


1  

In our commercial application, we had a very robust solution for that. The price was non-portability.

在我们的商业应用中,我们有一个非常强大的解决方案。价格是不可携带的。

We installed a Vectored Exception Handler. This handler is called in case of an unhandled OS exception, before the program exits (which is by far the most common crash). When it's called, you can not call C++ Standard Library function anymore (or even C functions). Even fflush is unreliable.

我们安装了一个矢量异常处理程序。在程序退出之前,在处理未处理的OS异常的情况下调用此处理程序(这是迄今为止最常见的崩溃)。当它被调用时,你不能再调用C ++标准库函数(甚至是C函数)。甚至fflush也不可靠。

Yet it is OK to call basic OS functions. Be careful, though. Setting up the arguments for the OS call shouldn't use malloc either. Have the name of the crashfile already set up before the crash actually happens, etc. Do close the file immediately, again using OS functions.

然而,调用基本的OS功能是可以的。但要小心。设置OS调用的参数也不应该使用malloc。在崩溃实际发生之前已经设置了崩溃文件的名称等。请使用OS功能再次立即关闭文件。

#1


3  

You should employ flush method, it is there to precisely solve problems like the one you're facing.

您应该使用flush方法,它可以精确地解决您所面临的问题。

There is another approach which can be considered more safe, but requires substantially more effort to implement and test. The approach boils down to what is known as inter-process communication (IPC). In brief, you could implement your logger as a separate logger application which would communicate with your target application by means of specific protocol (interface). You can develop such protocol by yourself or employ one of the existing ones (which are usually very generic, i.e. general purpose). As a result, if your target application crashes, it doesn't drag logger application with it, and therefore logger can safely finish its job.

还有另一种方法可以被认为更安全,但需要更多的努力来实施和测试。该方法归结为所谓的进程间通信(IPC)。简而言之,您可以将记录器实现为单独的记录器应用程序,该应用程序将通过特定协议(接口)与目标应用程序进行通信。您可以自己开发此类协议,也可以使用现有协议(通常非常通用,即通用)。因此,如果您的目标应用程序崩溃,它不会随之拖动记录器应用程序,因此记录器可以安全地完成其工作。

That approach is usually used by some huge, complex, and safety-critical systems. However, I guess that in your case this is definitely an overkill and bare flush() after each append is more than enough.

这种方法通常由一些庞大,复杂且安全关键的系统使用。但是,我想在你的情况下,这肯定是一个矫枉过正,并且在每次附加后勉强刷新()。

#2


1  

In our commercial application, we had a very robust solution for that. The price was non-portability.

在我们的商业应用中,我们有一个非常强大的解决方案。价格是不可携带的。

We installed a Vectored Exception Handler. This handler is called in case of an unhandled OS exception, before the program exits (which is by far the most common crash). When it's called, you can not call C++ Standard Library function anymore (or even C functions). Even fflush is unreliable.

我们安装了一个矢量异常处理程序。在程序退出之前,在处理未处理的OS异常的情况下调用此处理程序(这是迄今为止最常见的崩溃)。当它被调用时,你不能再调用C ++标准库函数(甚至是C函数)。甚至fflush也不可靠。

Yet it is OK to call basic OS functions. Be careful, though. Setting up the arguments for the OS call shouldn't use malloc either. Have the name of the crashfile already set up before the crash actually happens, etc. Do close the file immediately, again using OS functions.

然而,调用基本的OS功能是可以的。但要小心。设置OS调用的参数也不应该使用malloc。在崩溃实际发生之前已经设置了崩溃文件的名称等。请使用OS功能再次立即关闭文件。