Bug 5298 - ftell() after a write() causes glibc to flush the buffer
Summary: ftell() after a write() causes glibc to flush the buffer
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: stdio (show other bugs)
Version: unspecified
: P2 enhancement
Target Milestone: ---
Assignee: Ulrich Drepper
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-11-08 22:07 UTC by A. Waris Sindhi
Modified: 2014-07-04 06:59 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description A. Waris Sindhi 2007-11-08 22:07:53 UTC
Calling ftell() after a write() call causes glibc to flush the buffer. This
results in performance degradations for certain of our user applications where
we depend on knowing where the file-pointer while doing small record writes.
Below is  a sample code which demonstrates the issues that we are seeing

testwrite.c

#include <stdlib.h>

#define MEGABYTE 1048576

int main(int argc, char *argv[]) {
  int ret;
  char filename[512];
  char *data;
  int dsize, size, chunksize, count;
  FILE *myfile;

  int ftell_on = 0;
  chunksize = 208;

  //===============================================================
  // Process arguments
  //   <output_file>
  //   <write_size>
  //   <0/1>
  //===============================================================
  char *usage_str = "Usage arguments : <output_file> <file_size> <0/1> \n";
  if (argc < 3) {
    printf ("Invalid arguments : \n");
    printf ("\t %s \n", usage_str);
    return 1;
  }

  sscanf(argv[1],"%s",filename);
  sscanf(argv[2],"%d",&dsize);
  sscanf(argv[3],"%d",&ftell_on);

  dsize *= MEGABYTE;

  data=malloc(sizeof(char) * dsize);

  if(!data) {
    perror("malloc() failed");
    abort;
  }

  myfile = fopen(filename,"w");

  if(myfile == NULL) {
    perror("fopen failed()");
    abort;
  }

  for(count=0; count<dsize; count+=chunksize) {
    if(count+chunksize <= dsize) {
      size = chunksize;
    }
    else {
      size = dsize-count;
    }

    ret = fwrite(data,size,1,myfile);

    if(ret != 1) {
      perror("Write failed\n");
      abort();
    }

   if (ftell_on == 1) {
     int pos;
     pos = ftell(myfile);
     if (pos < 0) {
        perror("ftell() failed");
        abort();

     }
   }

  }
  ret = fclose(myfile);

}

gcc -o testwrite.exe testwrite.c

1. Run code with ftell on

strace ./testwrite.exe file 1 1

write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 208) = 208
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 208) = 208


2. Run code with ftell off 

strace ./testwrite.exe file 1 0


write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 32768) = 32768
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 32768) = 32768
Comment 1 Ryan S. Arnold 2007-11-09 14:07:43 UTC
Per the comments in libio/fileops.c (_IO_new_file_seekoff):

  /* Flush unwritten characters.
     (This may do an unneeded write if we seek within the buffer.
     But to be able to switch to reading, we would need to set
     egptr to ptr.  That can't be done in the current design,
     which assumes file_ptr() is eGptr.  Anyway, since we probably
     end up flushing when we close(), it doesn't make much difference.)
     FIXME: simulate mem-papped files. */

Ulrich, any ideas for a design addressing the FIXME suggestion?
Comment 2 Jan "Yenya" Kasprzak 2009-08-10 11:23:08 UTC
Hello, is anything new wrt. this bug? I have just ran into it on my RHEL and
Fedora systems.
Comment 3 Rich Felker 2012-02-21 16:38:08 UTC
Is this bug still unaddressed? I don't see how _IO_new_file_seekoff should even come into it, since the operation is ftell, not fseek; if this function is being called for ftell, that seems to be the whole problem...
Comment 4 Siddhesh Poyarekar 2012-09-07 11:12:01 UTC
I have posted a patch for this:

http://sourceware.org/ml/libc-alpha/2012-09/msg00198.html

for those who want to try this out.
Comment 6 Siddhesh Poyarekar 2012-09-28 13:31:21 UTC
forgot to close the bug.
Comment 7 Paul Pluzhnikov 2014-02-06 22:28:59 UTC
Fixes here appear to have caused
https://sourceware.org/bugzilla/show_bug.cgi?id=16532