[comp.unix.xenix] setvbuf

ked@garnet.berkeley.edu (Earl H. Kinmonth) (02/16/89)

In profiling a program using setvbuf(), I observed an unusually high
time usage by read and write. After hours of diddling, I found that
setvbuf() for SCO Xenix has a different calling sequence from the
setvbuf() in BSD UNIX and in the C libraries for Turbo C and other
Misery Dos compilers.

The common sequence is

setvbuf(stream,buffer,type,size)

The SCO sequence is

setvbuf(stream,type,buffer,size)

Since there is no function prototype in <stdio.h>, the parameter
mismatch will not show up unless you check the return value. (I
wasn't.) Even if you do, its not very informative.

If you have programs from Misery Dos or BSD UNIX that use setvbuf(),
you should probably check for this problem. It only produces slower io
since the next action on the stream will cause buffering, but ....

RHETORICAL QUESTION: Is there any good explanation for this useless
kind of difference, or was some programmer cranked up on weed when
he/she/it did the SCO version?

LESS RHETORICAL QUESTION: Why no prototype?

gene@zeno.MN.ORG (Gene H. Olson) (02/21/89)

Setvbuf appeared (I believe) in System V.2 with a direct conflict
between the Manual Pages that shipped on the system, and the
libraries and lint files.

For a good while there, parameters 2 & 3 were interchanged in
/usr/lib/llib-lc and in the libraries, while the manuals always
showed the parameters as:

	setvbuf(stream, buffer, type, size)

This *feature* made its way into a number of systems (including
XENIX) over the years, and has now been corrected in V.3.

It shouldn't be a problem to lint users, since (at least in my
experience) the lint on a system always agrees with the libraries.
This is just another reason why you should always use lint.

Gene H. Olson
gene@zeno.mn.org

rosso@sco.COM (Ross Oliver) (02/23/89)

In article <20422@agate.BERKELEY.EDU> ked@garnet.berkeley.edu (Earl H. Kinmonth) writes:
>setvbuf() for SCO Xenix has a different calling sequence from the
>setvbuf() in BSD UNIX and in the C libraries for Turbo C and other
>Misery Dos compilers.
>
>The common sequence is
>
>setvbuf(stream,buffer,type,size)
>
>The SCO sequence is
>
>setvbuf(stream,type,buffer,size)
>
>Since there is no function prototype in <stdio.h>, the parameter
>mismatch will not show up unless you check the return value. (I
>wasn't.) Even if you do, its not very informative.


This was discovered and corrected in the 2.3 release
of the Development System.  It was actually inherited
from Microsoft.

Backward compatibile objects exist for programs that can't
be recompiled and still expect the old sequence.  To use
these, you must use the -compat flag.  Otherwise, source
needs to be fixed to use the new libraries.

The prototypes for all library and system calls, including
the corrected setvbuf(), have been added to the #include
files in 2.3 Development System.

Ross Oliver
Technical Support
The Santa Cruz Operation, Inc.

ked@garnet.berkeley.edu (Earl H. Kinmonth) (03/14/89)

Several weeks ago, I posted a note to the effect that SCO Xenix
setvbuf is screwed up compared to more common setvbuf versions
because of the different calling conventions:

setvbuf(stream,buf,type,size)	/* common */

setvbuf(stream,type,buf,size)	/* sco */

I thought fixing this would correct some problems I had noted
with programs converted from 4.3 BSD or even MiSerable DOS.  This
has not been the case.  I've noted several instances of weird bugs
when using setvbuf() with SCO Xenix (the same programs run fine with
MiSerable DOS and 4.3 BSD).  They also run fine under SCO Xenix IF
setvbuf is commented out of the code. Specifically:

(a)
buf = malloc(size);
setvbuf(stream,type,buf,size);
stream->_flag & _IOMYBUF shows that _IOMYBUF is not set.

(b)
measured performance with sequential access (getc()) on large files
shows no improvement, even a degradation with size > BUFSIZ!  This
is disturbing, since MiSerable DOS and 4.3 BSD show improved performance
(elapsed time, number of calls to read()) with larger buffer sizes.

This suggests to me that not only is the parameter sequence for
setvbuf() assbackwards, but the actual realization of the function
is broken.

Note, to detect this, you must use prof and/or look at the times needed
to read/write a file.  Bad calls to setvbuf() apparently do no harm,
and the first io operation on stream gives you default buffering, so
unless you are making cross comparisons between systems, you probably
will see no problems.