From: MERC::"uunet!CRVAX.SRI.COM!RELAY-INFO-VAX" 29-DEC-1992 20:45 29-DEC-1992 20:45:00.00 To: INFO-VAX@kl.sri.com CC: Subj: re: Re: flushing in VAXC and DECC [fsync] In article <1992Dec27.055031.24162@eco.twg.com>, larry@eco.twg.com (Lawrence B. Henry III) writes: [VMS AXP HELP for fsync()] >PS. Don't take this serious unless you are one of those people out >there posing as a guru.. :-) Glad to know that it's documented on AXP machines. Now, perhaps you'd clarify a point for us: The AXP documentation doesn't agree with what fsync() acutally does under VMS 5.4-2. In particular, the AXP documentation would have us believe that: fsync(fileno(stdout)); actually causes the results of, e.g., all printf's to be flushed to disk. Now, under VMS 5.4-2, if you spawn a subprocess (using the command "SPAWN/NOWAIT/OUTPUT=file_name RUN program" that runs the program #include stdio main() { printf("This is a test."); fsync(fileno(stdout)); sleep(30); } guess what? You don't see "This is a test." in the output until the process dies. However, if the program had been: #include stdio main() { printf("This is a test."); fflush(stdout); fsync(fileno(stdout)); sleep(30); } you'd see "This is a test." in the output file right away. So, as someone "posing as a guru," I'd like to know whether the function does as it's documented to do, or whether it does what it does under VMS v5.4-2. (If you don't understand the distinction, that's OK; You're not "posing as a guru") Gee, now *I* get to flame Carl! Carl, you uneducated twit! Didn't you read my earlier posting on this subject? (It hasn't arrived at your site yet, you say? Hey, fool, if you aren't going to wait for those who know to explain it to you, why are you running your mouth off? And haven't you read the Unix BSD documentation yet?) :-) Seriously, to repeat: - fsync() is a Unix BSD (4.1BSD in fact, I believe - so quite old) invention. - On Unix, there is a clear division between the operating system I/O layer (open(), read(), write()) and the Standard I/O Library (fopen(), scanf(), printf()). You can tell which level a routine lives at by looking at how it specifies a file. The Unix layer specifies files using file descriptors, AKA file numbers. The Standard I/O Library specifies them using file pointers (objects of type FILE *). The only user-accessible function that crosses layers is fileno(), which gives you the file descriptor for the Unix layer file underlying a given Standard I/O Library. Functions that operate at the Unix layer are actually system calls (i.e., like VMS system services). Functions in the Standard I/O Library are just normal user-mode code. - Since, on Unix, fsync() operates at the Unix I/O level, one should no more expect it to flush the buffers of the Standard I/O layer "above" it than one should expect that, for example, intermixing printf's with write's to the underlying file will cause things to come out in the right order. Note that the Unix documentation doesn't actually SAY anything about this one way or the other; but it should be clear from context. - On VMS, there's a similar clear distinction (at least to those who understand such things) between the VAX C RTL's Unix emulation and the underlying RMS services. The problem people run into is that they forget that the line between emulated Unix layer calls and emulated Standard I/O Library calls is still there, too. (Or they think it's in another place. INFO-VAX has seen many questions from people who assumed that, for example, read() on VMS was "atomic" with respect to signals, as it is on Unix, where it's a system call.) Although they are all part of the VAX C RTL, the Unix layer functions are still quite distinct from the Standard I/O Library functions. fsync() does "just what it does on Unix": It causes the "system sublayer" (here, RMS) to flush any data. It doesn't affect the Standard I/O layer at all. - A long time ago, I spoke to the VAX C developers about the fsync() function. Apparently the reason it remained undocumented for so long - it's a trivial function, maybe 10 instructions long - was that there was a debate within the VAX C group as to whether fsync() should do an implicit fflush(). The "no" side of the argument was "Unix doesn't do it, why should the emulation?" The "yes" side of the argument was "that's right, Unix doesn't do it, and it confuses the hell out of people. Doing it does NOT violate the specification of the function (such as it is) since nothing anywhere tells you when data will NOT be flushed for a Standard I/O Library file in Unix; why shouldn't we do better?" Note that doing an implicit fflush() isn't quite trivial since there is no way to find the FILE *, if any, that refers to a given file descriptor without searching all the files the Standard I/O Library has open. There is no inherent reason why there should not be more than one FILE * refering to the same file descriptor; in fact, in the DECUS C I/O system, all Standard I/O level files that refer to the control terminal do share the same file descriptor. Since the overall design of the VAX C RTL's I/O system at least started out modeled on DECUS C's, it's possible that it does the same (though I don't think so). - As a final note, in general, where essentially the same function can be applied to both the Unix and Standard I/O layers, the former will be named "op" while the latter will be named "fop", as, for example, in open/fopen, stat/fstat. This would lead you to think that fsync() lived in the Standard I/O layer and expected a FILE * argument. Wrong. (There is also a sync() Unix system call, but it does something different.) Consistency? Don't expect it from Unix. -- Jerry