0


I have some doubt about how fprintf() works. I read that fprintf() is not guaranteed to perform atomic append operations to the file it's writing to. What does it mean in practice?
Consider the following simple situation, for example:
Inside the same folder I have different copies of the same code (code below) running simultaneously and printing values into a common file (Data.txt), for example:\

#define N 10000000
int main(){
    FILE* fp_Data;
    fp_Data=fopen("Data.txt", "a");

    srand48(time(NULL));

    int i;
    double u;
    for(i=0; i<N; i++){
        u = drand48();
        fprintf(fp_Data, "%f\n", u);
    }
    fclose(fp_Data);

}

could something go wrong (overwritten data/missing data)?
[EDIT]
As pointed by Damien there is a similar question about this problem(Is fprintf() thread safe?)
In that question it talks about from different threads of the same process, not indipendent processes pointing to the same FILE*.
In that case for POSIX standards (which is the one I should consider on any pc with unix SO?) guaranties the thread-safety, meaning I don't risk overwritten/missing data issues. My doubt now is:
Is it also true for indipendent processes pointing to the same FILE*?

user1172131
  • 103
  • 7
  • 2
    Does this answer your question? [Is fprintf() thread safe?](https://stackoverflow.com/questions/47930728/is-fprintf-thread-safe) – Damien Feb 23 '21 at 09:49
  • From what I read he 's talking about from different threads of the same process, not indipendent processes pointing to the same FILE*. Anyway, just to be sure having understood the answer, in his case (`fprintf()` calls from different threads of the same process), POSIX standards (which is the one I should consider on a pc with unix SO?) guaranties the thread-safety, meaning I don't risk overwritten/missing data issues. Is it right? – user1172131 Feb 23 '21 at 10:56
  • 1
    It is my understanding too. Note that I am not an expert in this field. However, the post i mentioned seems rather affirmative and clear. – Damien Feb 23 '21 at 11:07
  • "with different codes running simultaneously and printing values into a common file," --> Post the code used to open the file - especially the _mode_. – chux - Reinstate Monica Feb 23 '21 at 18:23
  • chux - Reinstate Monica, I added a concrete and simple case to better explain my doubt – user1172131 Feb 23 '21 at 18:56
  • A `FILE` is a process-local object, so there is no way to have multiple processes with the same `FILE *` – Chris Dodd Feb 23 '21 at 21:56

1 Answers1

1

As long as the file was opened in append mode, each underlying write to the file will atomically append to the file in question.

As long as the FILE is in line buffered mode AND no line is longer than the underlying buffer size of the FILE object, each line will be written with a single write call to the underlying file.

You use the "a" mode for fopen to open the file in append mode. You can use setvbuf to set the buffer size and buffering mode of the FILE immediately after opening it.

setvbuf(fp_Data, NULL, _IOLBF, 1024);

If you leave the FILE in the default block-buffered mode, it will write to the underlying file whenever the buffer fills, which will likely be in the middle of a line. This will lead to messed up lines in the file if multiple processes are writing in append mode.


Another approach is to explicitly fflush the FILE each time a "record" is complete (which might be mulitple lines). As long as your records are always smaller than the buffer size, this will result in each record being atomically appended to the file.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • Thank you Chris Dodd, very clear answer. I've only one doubt about the buffer managing: If I reduce the buffer (with respect to the default block mode), forcing it to line mode or no buffering mode, do I risk to miss some writing, if the disk is busy for a moment (the code pass to the nexts iteration and the disk can't call back the previous data)? I better exposed my doubt in the 2 following question: https://stackoverflow.com/questions/66332796/missing-data-printed-on-file-setting-a-null-buffer https://stackoverflow.com/questions/66305027/c-code-fprintf-print-on-file-less-times-than-expected – user1172131 Feb 24 '21 at 08:50
  • The first link is about the general buffer mechanism and the possibility to lost data in case of no buffering mode. The second is, instead, a real situation where I lost some data from `fprintf()` calls (I'm not sure what happened there) – user1172131 Feb 24 '21 at 08:57
  • 1
    On POSIX, unless there's a disk error, no data will be lost -- if no buffers are available, the write call will block waiting for the disk. If there is a disk error, it should be reported as a failure, either on a write (fprintf will fail, setting the error flag on the FILE) or on the close (fclose will fail). – Chris Dodd Feb 24 '21 at 18:42
  • To see when such disk error occour I have to explit check the return value of `fprintf()` and check if it is negative, right? For example with an if condition after the command `StampStatus = fprintf(fp_Data, "%f\n", u);` like that: `if(StampStatus <0){` `printf("fprintf writing error\n");` `}` "*fprintf will fail, setting the error flag on the FILE*" should I see the error flag in the file also without the previous if (or similar) check? – user1172131 Feb 25 '21 at 10:53
  • 1
    Either checking the return value of fprintf OR checking ferror(fp) afterwards is sufficient -- an error will set the flag and it will remain set until you explicitly clear it. However, even "success" generally just means that the data was successfully written to the kernel's buffer cache -- there might be a problem later when flushing the cache to the disk. Or the data might get corrupted on the disk after it is written. – Chris Dodd Feb 25 '21 at 19:25