I have traced some bug of using fputs and fflush in multi processes environment. So I coded simple code like below :
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "windows.h"
#define FILENAME "test.txt"
int main(int argc , char *argv[])
{
FILE *file;
file = fopen(FILENAME , "a");
char buf[10240 + 100];
int pid = GetCurrentProcessId();
char buf_pid[20];
itoa(pid, buf_pid, 10);
int ii = 0;
while(ii < 10000)
{
time_t now = time(0);
struct tm tstruct;
char tt[80];
tstruct = *localtime(&now);
strftime(tt, sizeof(tt), "%Y/%m/%d %X", &tstruct);
strcpy(buf, tt);
strcpy(buf + strlen(tt), " ");
strcpy(buf + strlen(tt) + 1, buf_pid);
strcpy(buf + strlen(tt) + strlen(buf_pid), " ");
int len = strlen(tt) + strlen(buf_pid) + 1;
int a = rand()%10240;
char temp;
for(int i=0;i<a;i++)
{
temp = 'a' + rand()%25;
memset(buf + len, temp, 1);
len++;
}
buf[len++] = '\n';
buf[len++] = 0;
//Sleep(1);
printf("%d %s %d %d\n", ii, tt, pid, a);
fputs(buf, file);
fflush(file);**
ii++;
}
And I runned with some batch file like below :
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
Then the result show like below , of course.
2019/11/08 22:57:14 261 rjatydimofugclqurclqecdrhvqsuwbvntmryktdl..
2019/11/08 22:57:14 261 ixoqldswtmhmjxqedqkprngproxvfpeuagbsxexje..
2019/11/08 22:57:14 261 skrhmutgpnkpwopudobptikjrfogdeairwyglcrqe..
2019/11/08 22:57:14 261 sqytmhtrnqkrtnfigwgcvvacgklmcjxinhehaqish..
2019/11/08 22:57:14 261 pvdvsfksuonldbwstvgflwjpecfymtfdrsnxlqqod..
2019/11/08 22:57:14 261 oqatxghvkhhjyvgnlymcjapedmpdakuuphbxnuqtd..
2019/11/08 22:57:14 261 ufrjkikbwvlvjejhpnndyebmgfjbmwvldsrlephow..
..
There is no explicit mutex, so fputs and fflush are not automic. I know fputs is to write the text into the file's buffer with it's handle in os kernel and fflush is to flush the buffer into the disk. And although there isn't synchronization objects, the order of accesses to the each buffer or flush code would be kept.
Is it possible to happen lock with above code? Or if there are 2 file that are being written by many processes, is it possible lock?
I found related good article but I don't convince it really happen. Is a sync/flush needed before writes to a locked file from multiple threads/processes in fopen a+ mode? fputs and fflush, writing and buffer process
Thanks!
There is a 'hidden' lock in the program - when the code opens the log file, it uses APPEND mode ("a" to open). This will result in the flag O_APPEND set on the open
system calls.
Quoting from man open:
O_APPEND The file is opened in append mode. Before each write(2), the file offset is positioned at the end of the file, as if with lseek(2). The modification of the file offset and the write operation are performed as a single atomic step.
The flag guarantee that each 'write' operation (which is executed whenever printf is executed to flush the lines to the file), will be atomic, and will not be mixed with output of other processes. The sync and the lock occurs within the operating system kernel, no user action is needed.