2

I'm having some issues with writing to a file whilst also having a delay in a while loop. Here's a snippet:

void main(int){
   FILE * fp = NULL;
   sprintf(filename, "log%i.msg", SET_ID);
   fp = fopen(filename, "w+");

   fprintf(fp, "File started\n");
   while(1){
      fprintf(fp, "%i %u %s\n", someInt, someUnsigned, someString);
      fflush(stdout);

      sleep(5); // Commenting out this line will work
   }
   fclose(fp);
   return 1;
}

Running the code gives me an output file of 0 bytes with nothing in it whilst the sleep is taking effect, although the file does have the expected content when my code finishes running. However, when I remove the sleep(5); line, it does print correctly. I've searched about this already, but what I've found is that it needs to be flushed, but I do this (though apparently incorrectly). What am I doing wrong?

mc110
  • 2,825
  • 5
  • 20
  • 21
jdepypere
  • 3,453
  • 6
  • 54
  • 84

1 Answers1

8

You're flushing stdout. You need to flush the file.

Change

fflush(stdout)

to

fflush(fp)

In terms of why the sleep() appears to impact whether contents are visible in the file: Without it present, you're writing to the file at a much higher rate, so you fill the in-memory buffer and flush to disk much faster. If you were patient enough, though, you'd see contents on-disk even with the sleep() present.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Now that's a really annoying mistake, didn't think it through I guess. Thanks, works with the correct flushing! – jdepypere Jun 07 '14 at 22:35
  • I thought fclose would flush before closing (http://man7.org/linux/man-pages/man3/fclose.3.html), so I don't understand why you had the original problem here, and why removing the sleep is relevant – mc110 Jun 07 '14 at 22:40
  • @mc110, indeed, closing a file does indeed implicitly flush. However, with an infinite loop, one could never reach it. – Charles Duffy Jun 07 '14 at 22:41
  • @Charles Duffy so can you explain the behaviour described by the OP? I feel like I must be being very stupid and missing something here. – mc110 Jun 07 '14 at 22:42
  • @mc110 Infinite loop. File never closed, program never exits. Removing the sleep, we write much faster, so we fill the buffer and end up flushing it implicitly. If the user were patient enough, they'd see contents in the file even with the sleep. – Charles Duffy Jun 07 '14 at 22:43
  • @Charles Duffy - aha, just read the title to make sense of things - the user sees the output on the close, but not before. They expected the erroneous fflush to make the file contents appear immediately, so question text of "Running the code gives me an output file of 0 bytes with nothing in it" was a bit misleading. The file is not 0 bytes when the problem has finished running with the sleep in it. – mc110 Jun 07 '14 at 22:45
  • Exactly. I've tried to edit the title to make it a bit more representative. – Charles Duffy Jun 07 '14 at 22:46
  • So what happens to the data if it's in the buffer but the program is closed before it's flushed and/or closed? If I remove the flush and wait a verrrrry long time, the data still isn't written. – jdepypere Jun 07 '14 at 22:49
  • 1
    http://stackoverflow.com/questions/8175827/what-happens-if-i-dont-call-fclose-in-a-c-program suggests that as long as your program ends normally the stream will be flushed. I'm not aware of what guarantees you have if you do a write and the program stays open indefinitely without flushing or closing. I suspect in this case you might never see the output - that is consistent with what I've seen with C programs which generate a small amount of output infrequently in the past without flushing or closing. – mc110 Jun 07 '14 at 22:54
  • 1
    @arbitter, it's not the amount of time being slept, but the amount of data that accumulates in the buffer that matters for purposes of triggering a flush; increasing the sleep won't help, and how "verrry" long of a time you wait is irrelevant -- only the quantity of buffered data that accumulated in that time matters. As for what guarantees you do or don't have about persistence after a signal-driven exit -- that's subject to your local standard C library's implementation, and also on what kind of signal is being handled (a SIGTERM allows more opportunities to flush than a SIGKILL). – Charles Duffy Jun 07 '14 at 23:21