[comp.unix.questions] fopen bug in Interactive ix/386 ?

news@edvcom.UUCP (News Admin) (05/03/89)

The following pice of code hangs because it tries to fopen() more than
_NFILE files. Insteed of returning a NULL pointer after the 18th call
it returns a 'valid' descriptor and chrashes.
We are using 1.0.6.
Any suggestions, maybe someone at ico.ISC.COM reading this group ?

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>

int a = 1;

int print_iob()
{
        int i, cnt, file;
        
        for (i = 0; i < _NFILE; i++)
        {
                cnt = _iob[ i ]._cnt;
                file = _iob[ i ]._file;
                printf("        FD(%d)   _cnt = %d  _file = %d\n",i,cnt,file);
        }
}

main(argc, argv)
int argc;
char *argv[];
{
        int     fod[ 200 ], i, num_opens;
        FILE    *fd[ 200 ];
        char    *msg;
        
                if (argc == 2)
                        num_opens = atoi(argv[ 1 ]);
                else
                {
                        printf("Specify number of open()'s \n");
                        exit(-1);
                }
                for (i = 0; i < num_opens; i++)
                {
                        fod[ i ] = open("/dev/null",O_WRONLY);
                        printf("errno=%d,variable=%d,FOD(%d)=%d\n",
                                                errno,a,i,fod[ i ]);
                }
                for (i = 0; i < 30; i++)
                {
                        printf("fopen (%d): ",i);
                        fflush(stdout);
                        if (fd[ i ] = fopen("/dev/null","w"))
                        {
                                printf("errno=%d,variable=%d,FD(%d)=%d\n",
                                                errno,a,i,fileno(fd[ i ]));
                                print_iob();
                        }
                        else
                        {
                                printf("fopen(%d) delivered NULL...\n",i);
                                break;
                        }
                }
                getchar();
                exit(0);

}  /* end main() */

+-----------------------------------------------------------------------------+
| G}nther Moschen              |   UUCP  : ...!uunet!mcvax!unido!edvcom!gm    |
| EDV-COMPAS Gmbh              |   FAX   : +49 8331 84024                     |
| 8940 Memmingen  W-Germany    |   PHONE : +49 8331 86078                     |
+------------------------------+----------------------------------------------+

larry@hcr.UUCP (Larry Philps) (05/09/89)

In article <314@edvcom.UUCP> news@edvcom.UUCP writes:
>
>The following pice of code hangs because it tries to fopen() more than
>_NFILE files. Insteed of returning a NULL pointer after the 18th call
>it returns a 'valid' descriptor and chrashes.
>We are using 1.0.6.
>Any suggestions, maybe someone at ico.ISC.COM reading this group ?

Actually, there is nothing "wrong" here at all - the file descriptor really
is valid.  In System V Rel 3, you can configure the number of allowed open
file descriptors to be anything between 20 and 100.  However in stdio.h you
find

...
#ifndef _NFILE
#define _NFILE	20
...

and in .../lib/libc/port/stdio/data.c you find

...
#include <stdio.h>
...
FILE _iob[_NFILE] = {
...
};

Fopen does not keep track of the number of open stdio streams, so when
finally fd #20 is returned by the kernel, you start clobbering random data in
you program until it crashes.  You can fix the behaviour by configuring your
kernel to only allow 20 open file descriptors, but this may break other
applications that do not use stdio and use lots of fds.

The real solution is to fix fopen to malloc a new iob when it runs out of
statically allocated ones, and make sure that the stdio macros and routines
can access and free these malloced iob's without trouble.  If you don't have
the source, then you are out of luck.

Larry Philps                             HCR Corporation
130 Bloor St. West, 10th floor           Toronto, Ontario.  M5S 1N5
(416) 922-1937                           {utzoo,utcsri,uunet}!hcr!larry

ross@mcdphx.UUCP (Ross Inglis) (05/12/89)

>In article <314@edvcom.UUCP> news@edvcom.UUCP writes:
>>The following pice of code hangs because it tries to fopen() more than
>>_NFILE files. Insteed of returning a NULL pointer after the 18th call
>>it returns a 'valid' descriptor and chrashes.
>>We are using 1.0.6.

In article <579@hcr.UUCP> larry@zeus.UUCP (Larry Philps) writes:
>Actually, there is nothing "wrong" here at all - the file descriptor really
>is valid.  In System V Rel 3, you can configure the number of allowed open
>file descriptors to be anything between 20 and 100.  However in stdio.h you
>find

Sorry, I think there's something wrong...
I was recently looking at the same problem on MCD's version of SysV. 
I found a bad loop in the stdio routine findiop().  The loop would
incorrectly return one more _iob than was legal, because it assumed
that a pointer _lastbuf was pointing to the last useable buffer when, in
fact, it pointed PAST the last buffer.  We recoded the five-line loop which
fixed the hang-up problem and allowed stdio to happily return a NULL
pointer after 20 (or whatever) files even though the kernel had NOFILES set
to 100.

BTW The hang appeared to be due to the fact that the sprintf() routine
reserves that last + one buffer for its personal use (and expects it to
remain unused).

Ross.

jbu@sfsup.UUCP (+Urban J.) (05/13/89)

In article <314@edvcom.UUCP> news@edvcom.UUCP (News Admin) writes:
>
>The following pice of code hangs because it tries to fopen() more than
>_NFILE files. Insteed of returning a NULL pointer after the 18th call
>it returns a 'valid' descriptor and chrashes.
>We are using 1.0.6.
>Any suggestions, maybe someone at ico.ISC.COM reading this group ?
>

In UNIX System V/386 Release 3.2, this bug DOES NOT EXIST.  UNIX System V/386
Release 3.2 allows 60 file descriptors so after 0,1,2 (stdin, stdout, stderr)
are gone, we really have 57 file descriptors.  I ran this test to see if UNIX
System V/386 Release 3.2 had the bug at 58 and it does not!

Sincerely,

John Urban