目标:如果由于某些奇怪的原因导致程序挂起/卡住,请将This line must be printed
写入日志文件mib_log_test
。
为简单起见,编写了如下的C程序:
#include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "./mib_log_test"
FILE *fp = NULL;
int main()
{
fp = fopen(FILE_NAME, "w+");
if (fp == NULL) {
fprintf(stderr, "Unable to open %s file", FILE_NAME);
exit(EXIT_FAILURE);
}
fprintf(fp, "This line must be printed\n");
while(1);
return 0;
}
在上面的程序上编译和运行时,它永远不会因无限循环而终止。因此,我必须按ctrl + c
才能终止它。使用ctrl + c
时,我看不到This line must be printed
被写入日志文件(mib_log_test
)
如果如下所示覆盖默认的SIGINT处理程序,则This line must be printed
将写入我的日志文件(mib_log_test
)中。
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#define FILE_NAME "./mib_log_test"
FILE *fp = NULL;
void sigint_handler(int sig_num)
{
exit(EXIT_FAILURE);
}
int main()
{
fp = fopen(FILE_NAME, "w+");
if (fp == NULL) {
fprintf(stderr, "Unable to open %s file", FILE_NAME);
exit(EXIT_FAILURE);
}
signal(SIGINT, sigint_handler);
fprintf(fp, "This line must be printed\n");
while(1);
return 0;
}
问题:哪种默认的SIGINT处理程序会导致在上述情况下不写入日志消息?
答案 0 :(得分:2)
default SIGINT handler terminates the process abnormally。 This means _exit
被调用,它不会刷新缓冲区。
作为一个旁注,从信号处理程序中调用exit
(确实是刷新缓冲区)是不安全的(only async-safe functions should be called from signal handlers)。因此,这不是解决您问题的真正方法。
即使您确实希望在日志文件中显示fflush(fp);
,也可以在fprintf
之后添加#include <signal.h>
static volatile sig_atomic_t keepRunning = 1;
void sigHandler(int sig) {
keepRunning = 0;
}
int main(void) {
signal(SIGINT, sigHandler);
while (keepRunning) {
/* normal operation, including logging */
}
/* cleanup */
return 0; /* this will close (and thus flush) the log file */
}
。
但是冲洗可能是相当昂贵的。如果您希望避免刷新每条日志行,但仍然希望在接收SIGINT时刷新日志文件,则一种方法是:
Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: org/netbeans/lib/awtextra/AbsoluteLayout
....
....
Caused by: java.lang.ClassNotFoundException: org.netbeans.lib.awtextra.AbsoluteLayout
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 17 more
关键是真正的清理(通常不是异步安全的)不会在信号处理程序本身中发生。
答案 1 :(得分:2)
默认情况下,Stdio文件缓冲区是块缓冲的,当它崩溃时,它不会刷新文件缓冲区,因此缓冲的输出会丢失。
一种解决方案是在每个<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
<div id="links">
<h1><a>link1</a></h1>
<div><h2><a> link2</a></h2></div>
<div><h2><a> link3</a></h2></div>
<div><h2><a> link4</a></h2></div>
<div><h2><a> link5</a></h2></div>
<div><h2><a> link6</a></h2></div>
<div><h2><a> link7</a></h2></div>
</div>
</body>
之后调用fflush(fp)
,但这很繁琐。
另一种解决方案是在打开文件后立即使用setvbuf
将文件设置为行缓冲模式,以便它为您刷新每个换行符号上的缓冲区:
fprintf(fp, ...)
这也使fp = fopen(FILE_NAME, "w+");
setvbuf(fp, NULL, _IOLBF, BUFSIZ);
立即和逐行输出,而不是延迟输出和成块输出。