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