最近碰到一个跟多线程程序 IO 有关的 bug。看来即使 stdio 函数是线程安全的,在处理多线程 IO 的时候还是得当心。
程序有两个线程,一个线程用 fprintf 输出大量日志,另一个线程在特定条件下会调用 exit 退出。调试半天以后发现在问题出在 exit 时,日志文件会出错。(比如少掉一个换行,出现重复的 log entry 或者丢掉一些 log 等等。)
原以为 exit 时,所有输出都会被 flush 出去。但回头想想,如果 fprintf 正在执行,而整个进程退出了,那缓存着的日志自然不能保证完全写出。(不知道为啥一开始调试的时候没想到。。。)
如果执行 exit 之前由该线程调用 fflush 还是会出同样的问题,因为另外一个线程可能在 fflush 执行完,而 exit 执行前输出日志。
最后的解决办法是在遇到特定退出条件时设置标志变量,输出日志的线程看到这个标志设置后调用 fflush 并且不再输出日志。