Thread: fflush() not working with Windows 7

  1. #16
    Registered User
    Join Date
    Jun 2010
    Location
    Michigan, USA
    Posts
    143
    The discussion in the thread "fflush() has no effect on file streams opened with _fsopen() on Windows 7" in the Visual C++ Developer Center Visual C++ General forum may give you a clue even if it is not directly your problem.

  2. #17
    Registered User
    Join Date
    Aug 2010
    Location
    England
    Posts
    90
    I found that discussion already.

    It is mentioned in a number of sites, and the solution - not mentioned in that particular set of posts - is that you have to delay by 6 seconds between opening a file and using the file due to caching issues on Windows 7. Or you have to disable caching altogether.

    Since our software will not be the only application running, I'm reluctant to impact on other vendors software in this way.

    You are right - it shows that there is a problem in Windows 7 to do with the caching mechanism.

    I have used setvbuf() to disable caching, and although you would think that this would fix the problem by effectively removing buffering, it still does not release characters at the end of a file.

    I have to output to machines that depend on a precise number of characters in a file, so I can't add extra characters to force the flush.

  3. #18
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by johnggold View Post
    Can someone please answer my question instead of talking about different compiler versions - already eliminated as the problem before I started posting.
    Really? You used a newer version of Visual Studio (which one?) and made a sample app that would write to disk then fflush, and you tested this until you found it still didn't work?
    You do realise that if you don't want us to suggest things you have already tried then it is your responsibilty to inform us of such things up front so we will know what not to suggest, right?

    Quote Originally Posted by johnggold View Post
    I found that discussion already.

    It is mentioned in a number of sites, and the solution - not mentioned in that particular set of posts - is that you have to delay by 6 seconds between opening a file and using the file due to caching issues on Windows 7. Or you have to disable caching altogether.
    I just read that article and the solution was actually to link to commode.obj. Have you tried that?
    More information here: How To Force Files to Be Flushed to Disk
    Last edited by iMalc; 08-16-2010 at 02:48 AM.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  4. #19
    Registered User
    Join Date
    Aug 2010
    Location
    England
    Posts
    90
    commode.obj forces all file opening to commit mode

    Code:
    /* set default file commit mode to commit */
    int _commode = _IOCOMMIT;
    This is already in our low level library

    I do think it's a bug in Windows 7 that will eventually get fixed - trouble is I can't really wait on Microsoft timescales.

    I originally thought it might be a removable media issues because the code normally writes direct to floppies or memory sticks for machine control.

    However, when I wrote to c:\TEMP then used Explorer to manually move the file there was the error again.

    Writing first to X:\TEMP - anywhere but a local Windows 7 drive works - presumably because the fflush() control is distributed to the remote PC/server.

    As a quick fix, I've a batch file that copies back. I've got file copy code which uses _open,_close instead of fopen, fclose, fflush so I will experiment to see if the bug is not there as well.
    Never re-write code unless the user benefits

  5. #20
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Code:
        if (fflush(f) != 0)
            perror("fflush");
        
        if (_commit(_fileno(f)) != 0)
            perror("_commit");
    
        if (fclose(f) != 0)
            perror("fclose");
    If that doesn't work, would you provide a small console application that reproduces the issue.

    gg

  6. #21
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,667
    > I just read that article and the solution was actually to link to commode.obj. Have you tried that?
    commode is just a fantastic name for a library, given all the flushing going on and all

    > I do think it's a bug in Windows 7 that will eventually get fixed - trouble is I can't really wait on Microsoft timescales.
    Tell me, why did you decide to jump to the latest offering from M$ before it's first diaper change?

    I mean, you made all this noise about "stability" (that's why you're sticking with VC6), but you go and jump on the most untested OS out there.

    I take it when you said in #1 "not windows7", that you meant something like XP? So why not deploy that instead if it works.

    Have you got as far as raising a bug report with Microsoft?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #22
    Registered User
    Join Date
    Aug 2010
    Location
    England
    Posts
    90
    Unfortunately we have no control over which PC's our Customers buy.

    The first instance we saw was a Customer who scrapped all his XP PC's and installed Windows 7.

    As all our multiuser software is client server, with no software resident on the PCs, it just needs a shortcut on the desktop and it all works, so Customers can run on whatever they have.

    NB: Licensing is via the server engine.

    We already have a number of 2008 server/Windows 7 installations using exactly the same software, so we did not expect problems.

    Unfortunately this Customer has an old DOS based manufacturing machine that likes floppy discs and can't be networked, so that's why the problem appeared there.

    To be fair to Windows 7 this is the first (and only) problem we've found. Our applications run really well.

    I have attempted to raise a fault with Microsoft, although from past experience this is a waste of time.

    There already is a fault report raised with Microsoft on a possibly related problem of writing to newly created files, which does not seem to have been fixed.

    But you never know with Microsoft. My Windows 7 laptop installed a load of updates today - haven't had time to check them yet.
    Never re-write code unless the user benefits

  8. #23
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    Quote Originally Posted by Salem View Post
    commode is just a fantastic name for a library, given all the flushing going on and all
    Fantastical, even.

  9. #24
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by johnggold View Post
    I have attempted to raise a fault with Microsoft, although from past experience this is a waste of time.
    Ah good. I was going to suggest that. Unfortunately I too expect that it may be fruitless as has been the case of the ones our company has reported to Microsoft, but you never know.

    Quote Originally Posted by johnggold View Post
    However, when I wrote to c:\TEMP then used Explorer to manually move the file there was the error again.
    That's actually highly surprising.
    Obviously one can only move a file that is closed, and a closed file not being fully updated really sounds like a major bug that would affect thousands of apps, not the least of which would be Internet Explorer. However, when IE downloads a file it first writes it to some temp location and then moves it to the right place when it completes, basically exactly what you are doing as a workaround - interesting.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  10. #25
    Registered User
    Join Date
    Aug 2010
    Location
    England
    Posts
    90
    The damage seems to be done on initial writing - the file closes incomplete. IE then moves what it has.

    Also puzzling is that there is apparently no relation to buffer size - you would expect that with a 1024 buffer size, the damaged file would be an exact multiple - signifying that no flushing takes place, but that is not the case.

    The output file is pure text - mostly G codes

    G0 X100, Y1000
    G1 X200, Y2000
    etc

    fflush() is only called on close file. Strictly speaking fclose flushes anyway, but fflushing first is belt & braces.

    I'm going to write a small app, simulating the method by which characters are sent to the file.
    Never re-write code unless the user benefits

  11. #26
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> I'm going to write a small app, simulating the method by which characters are sent to the file.
    Posting the .dsp, makefile, etc. would be helpful too. I'm interested in what the root of this one is.

    gg

  12. #27
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    I have a very simple test-harness below that runs ok:
    Code:
    #include <stdio.h>
    
    int main()
    {
        const int file_size = 1024 * 512;
        const char line_fmt[] = "I declare this to be line number %04d\n";
        const int num_lines = file_size / sizeof(line_fmt); // approx.
        int n;
    
        FILE *f = fopen("vc6_on_w7.txt", "w");
        if (!f)
            perror("fopen");
    
        if (fprintf(f, "Writing %d lines\n", num_lines) < 0)
            perror("fprintf");
    
        for (n = 0; n < num_lines; ++n)
            if (fprintf(f, line_fmt, n + 1) < 0)
                perror("fprintf");
    
        if (fflush(f) != 0)   
            perror("fflush");
    
        if (fclose(f) != 0)
            perror("fclose");
    
        return 0;
    }//main
    I've got 6.0 Enterprise SP6 on XP. Test runs on Win7 x64.

    What kind of things can I throw in there that may help to reproduce the issue? Or even better would be code that repro's the issue

    gg

  13. #28
    Registered User
    Join Date
    Aug 2010
    Location
    England
    Posts
    90
    Apologies for the delay - been away at a wedding.

    Code:
       if (fflush(f) != 0)   
            perror("fflush");
    
        if (fclose(f) != 0)
            perror("fclose");
    Problem is .. this code should generate an error, but doesn't. If it did, I could loop.

    So the OS says everythings fine, but it isn't!

    I've only seen missing data at the end of the file, but that's to be expected, since the output is not re-read at any stage.

    I do have an application that has to treat the sequence file as random access, and seeks back to the first "record" to change values in the first record, once the total file size is known, but I haven't needed this on a Windows 7 site, so no chance to check.

    I'm just waiting to see if using setvbuf() to no buffering works.
    Never re-write code unless the user benefits

  14. #29
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    setvbuf() only affects the in-process buffer used by the CRT. For example, "setvbuf(f, 0, _IONBF, 0)" will cause your fwrites to go straight through to WriteFile(). This may only hide the bug.

    It's extremely unlikely that there is a bug in the Win32 API, or in the MSVCRT.DLL that ships with Win7.

    If you post code that reproduces the issue, we'll be able to tell you want the problem is and how to fix it. If you can't reproduce it with a simple console app that writes just like the real app - that's just evidence that the bug is in the real app.

    gg

  15. #30
    Registered User
    Join Date
    Aug 2010
    Location
    England
    Posts
    90
    Your code sample is very similar to my actual code. Here are the open, close functions.

    Code:
    FHANDLE G3createfile(BYTEP filename)
    {
    FILE *fp;
    
    RESULT2 = 0;
    FileErrSimple = _T("");
    FileErrDetail = _T("");
    
    
    if (filename == NULL)
    	{
    	 MessageBox(NULL, _T("createfile() called with NULL filename"), _T("Coding error"), MB_OK | MB_ICONSTOP);
    	 return NULL;
    	}
    
    if (strlen((const char *)filename) < 2)
    	{
    	 MessageBox(NULL, _T("createfile() called with short filename"), _T("Coding error"), 
                                          MB_OK | MB_ICONSTOP);
    	 return NULL;
    	}
    
    if( ( fp = fopen( (const char *)filename, "w+bc" ) ) == NULL )
    	{
             RESULT2 = 2;
    
             fperror( filename, RESULT2 );
    
             return ( NULL );
    	}
    else
    	{
             // No buffers required
             setvbuf( fp, NULL, _IONBF, 0 );
    
             return( fp );
            }
    }
    
    void G3closefile(FHANDLE fp)
    {
    if (fp == NULL)
    	{
     	 MessageBox(NULL, _T("closefile() called with NULL handle"), _T("Coding error"),     
                                          MB_OK | MB_ICONSTOP);
    
    	 return;
            }
    
    fflush( fp );
    
    // Go back to origin
    fseek( fp, (long) 0, FS_SET );
    
    fflush( fp );
    fclose( fp );
    }
    The setvbuf() and fseek to zero lines have been added as workarounds, for obvious reasons. The fseek() fixed larger files, but not smaller ones - hence setvbuf() was a logical next step.

    fwrite() is used to write to the file. All output is standard text characters with CR/LF's.

    The code is widely used across a large number of our applications, and there are only two combinations of failure on Win7 PC networks. Either ALL PCs's are Win7 (peer to peer network, or Win7 is connected to 2008 server.

    Win7 PC's on a 2003 network do not exhibit this problem.
    Never re-write code unless the user benefits

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Do I need to wait in between fclose() and fopen()?
    By patiobarbecue in forum C Programming
    Replies: 7
    Last Post: 07-06-2010, 04:33 PM
  2. Just starting Windows Programming, School me!
    By Shamino in forum Windows Programming
    Replies: 17
    Last Post: 02-22-2008, 08:14 AM
  3. how to make a windows application
    By crvenkapa in forum C++ Programming
    Replies: 3
    Last Post: 03-26-2007, 09:59 AM
  4. Script errors - bool unrecognized and struct issues
    By ulillillia in forum Windows Programming
    Replies: 10
    Last Post: 12-18-2006, 04:44 AM
  5. Replies: 3
    Last Post: 08-18-2004, 07:39 AM