[comp.sys.hp] Strange behaviour on HP9000/825

martin@innovus.UUCP (Martin Renters) (07/26/89)

We just found some rather strange behaviour on our 9000/825 running
HP-UX 3.0.  Seems we get an errno 25 (not a typewriter) on the first
I/O we do on any newly opened file, although the I/O is actually carried
out. Any subsequent I/Os work fine, without error. Both HFS and NFS
filesystems seem to have this problem.

Here's a test program (a.c) that illustrates this problem:

#include <stdio.h>
#include <errno.h>
extern int errno;

main()
{
	FILE *fp; char buffer[80];
	buffer[0]='\0';

	if ((fp=fopen("a.c","r")) == NULL)
	{
		printf("File fails to open\n");
		exit(2);
	}
	printf("File opens, errno=%d, fp=%d\n",errno,fp);
	fgets(buffer,64,fp);
	printf("File read, errno=%d, fp=%d, buffer=%s",errno,fp,buffer);
	clearerr(fp); errno=0;
	fgets(buffer,64,fp);
	printf("File read2, errno=%d, fp=%d, buffer=%s",errno,fp,buffer);
}

When compiled with 'cc a.c' and executed the following output results:

File opens, errno=0, fp=1073742056
File read, errno=25, fp=1073742056, buffer=#include <stdio.h>
File read2, errno=0, fp=1073742056, buffer=#include <errno.h>

Anybody care to comment about why this is happening?


Martin Renters				martin@innovus
Technical Analyst			..utgpu!maccs!innovus!martin
Innovus Inc.

fkittred@bbn.com (Fletcher Kittredge) (07/26/89)

In article <227@innovus.UUCP> martin@innovus.UUCP (Martin Renters) writes:
>
>We just found some rather strange behaviour on our 9000/825 running
>HP-UX 3.0.  Seems we get an errno 25 (not a typewriter) on the first
>I/O we do on any newly opened file, although the I/O is actually carried
>out. Any subsequent I/Os work fine, without error. Both HFS and NFS
>filesystems seem to have this problem.

>File opens, errno=0, fp=1073742056
>File read, errno=25, fp=1073742056, buffer=#include <stdio.h>
>File read2, errno=0, fp=1073742056, buffer=#include <errno.h>
>
>Anybody care to comment about why this is happening?
>

Sure, I'll comment.  I think you have a fundamental misunderstanding of
errno.  It is only guaranteed to be set to a meaningfull value after a
system call fails.  Since you don't check to see if a system call fails,
basically what your code is doing is checking the value of an uninitialized
variable.  As one might expect, you get garbage.

I recommend the following books:

"The Unix Programming Environment"
Kernighan and Pike
Prentice-Hall, 1984

"Advanced Unix Programming"
Rochkind
Prentice-Hall, 1985

regards,
fletcher
Fletcher E. Kittredge  fkittred@bbn.com

jack@csccat.UUCP (Jack Hudler) (07/27/89)

In article <227@innovus.UUCP> martin@innovus.UUCP (Martin Renters) writes:
>
>We just found some rather strange behaviour on our 9000/825 running
>HP-UX 3.0.  Seems we get an errno 25 (not a typewriter) on the first
>I/O we do on any newly opened file, although the I/O is actually carried
>out. Any subsequent I/Os work fine, without error. Both HFS and NFS
>filesystems seem to have this problem.

It is my understanding that errno is only checked when you have an
error, not to indicate that one occured. If no error from the function
call is returned, then the value of errno is meaningless.

-- 
Jack 		Computer Support Corportion		Dallas,Texas 
Hudler		UUCP: {texsun,texbell,attctc}!csccat!jack

stroyan@hpfcdc.HP.COM (Mike Stroyan) (07/27/89)

> File opens, errno=0, fp=1073742056
> File read, errno=25, fp=1073742056, buffer=#include <stdio.h>
> File read2, errno=0, fp=1073742056, buffer=#include <errno.h>
> 
> Anybody care to comment about why this is happening?

The fopen is checking isatty() to see if it should buffer the stream
output.  The isatty call is using a failed ioctl() call to see that the
file is not a tty.  The failed ioctl() call is setting errno to ENOTTY.

Your program is checking the value of errno without first checking
ferror() or the return value from fgets().  You can't depend on the
value of errno being to be 0 when an error has not occured.  You must
first determine that an error occured, then use errno to find out more
about the error.  The errno value is not always defined to reflect the
state of libraries such as stdio.  While some library calls will refer
the user to errno for more information, it is really intended to return
information about kernel calls rather than arbitrary library calls.

Mike Stroyan, stroyan@hpfcla.hp.com

walter@hpclwjm.HP.COM (Walter Murray) (07/28/89)

Several others have pointed out the problem of checking errno when no
error condition has been indicated.  Here are a few more interesting
things to know about errno, which will be true in any ANSI-conforming
compiler and library.

1.  The value of errno is always zero at program startup.

2.  The program itself may set errno to zero, but none of the standard
    library functions will ever do so.

3.  Even though any particular library function may not be documented
    to use errno, it is possible that that function will set errno
    to a nonzero value, regardless of whether an error occurred.

4.  For portability, it is better not to declare errno yourself.
    Just include <errno.h> and rely on the declaration there.
    On some systems, errno will be a macro, and if you try to
    declare it yourself as 'extern int', there'll be a problem.

Walter Murray
Hewlett-Packard
----------------------------------------------------------------------

corrigan@net1.ucsd.edu (Mike Corrigan) (07/28/89)

In article <227@innovus.UUCP> martin@innovus.UUCP (Martin Renters) writes:

>	printf("File opens, errno=%d, fp=%d\n",errno,fp);
/*
>	fgets(buffer,64,fp);
>	printf("File read, errno=%d, fp=%d, buffer=%s",errno,fp,buffer);
*/
Should go like:

	while(fgets(64,fp) != NULL)
		printf("File read, buffer=%s",buffer);
	if(!feof(fp)) {
		fprintf(stderr,"ERROR detected on File read\n");
		exit(ferror(fp));
	}