working of fwrite in c++

Bill picture Bill · Dec 22, 2012 · Viewed 9.7k times · Source

I am trying to simulate race conditions in writing to a file. This is what I am doing.

  1. Opening a.txt in append mode in process1
  2. writing "hello world" in process1
  3. prints the ftell in process1 which is 11
  4. put process1 in sleep
  5. open a.txt again in append mode in process2
  6. writing "hello world" in process2 (this correctly appends to the end of the file)
  7. prints the ftell in process2 which is 22 (correct)
  8. writing "bye world" in process2 (this correctly appends to the end of the file).
  9. process2 quits
  10. process1 resumes, and prints its ftell value, which is 11.
  11. writing "bye world" by process1 --- i assume as the ftell of process1 is 11, this should overwrite the file.

However, the write of process1 is writing to the end of the file and there is no contention in writing between the processes.

I am using fopen as fopen("./a.txt", "a+)

Can anyone tell why is this behavior and how can I simulate the race condition in writing to the file?

The code of process1:

#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include "time.h"
using namespace std;
int main()
{

    FILE *f1= fopen("./a.txt","a+");
    cout<<"opened file1"<<endl;
    string data ("hello world");
    fwrite(data.c_str(), sizeof(char), data.size(),  f1);
    fflush(f1);
    cout<<"file1 tell "<<ftell(f1)<<endl;
    cout<<"wrote file1"<<endl;
    sleep(3);
    string data1 ("bye world");;
    cout<<"wrote file1 end"<<endl;
    cout<<"file1 2nd tell "<<ftell(f1)<<endl;
    fwrite(data1.c_str(), sizeof(char),  data1.size(),  f1);
    cout<<"file1 2nd tell "<<ftell(f1)<<endl;
    fflush(f1);
    return 0;
}

In process2, I have commented out the sleep statement.

I am using the following script to run:

./process1 &
sleep 2
./process2 &

Thanks for your time.

Answer

sqreept picture sqreept · Dec 22, 2012

Writing in append mode is an atomic operation. This is why it doesn't break.

Now... how to break it?

Try memory mapping the file and writing in the memory from the two processes. I'm pretty sure this will break it.