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.
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.
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.
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?
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"
commode.obj forces all file opening to commit mode
This is already in our low level libraryCode:/* set default file commit mode to commit */ int _commode = _IOCOMMIT;
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
If that doesn't work, would you provide a small console application that reproduces the issue.Code:if (fflush(f) != 0) perror("fflush"); if (_commit(_fileno(f)) != 0) perror("_commit"); if (fclose(f) != 0) perror("fclose");
gg
> 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.
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
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.
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"
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
>> 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
I have a very simple test-harness below that runs ok:
I've got 6.0 Enterprise SP6 on XP. Test runs on Win7 x64.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
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
Apologies for the delay - been away at a wedding.
Problem is .. this code should generate an error, but doesn't. If it did, I could loop.Code:if (fflush(f) != 0) perror("fflush"); if (fclose(f) != 0) perror("fclose");
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
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
Your code sample is very similar to my actual code. Here are the open, close functions.
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.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 ); }
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