[comp.unix.sysv386] TLI Programming, t_free

kjd@icxn.UUCP (Kevin J. Dunlap) (05/17/91)

I am having a problem with memory and using AT&T's TLI running on
Interactive 386/ix System V 3.2.2.  I have the updates to TCP/IP
installed (SSU.4a).

The problem is that it looks like t_free() is not freeing up the memory
allocated by t_alloc().  As the process runs, it calls t_alloc to
allocate the T_UNITDATA and then calls t_free to free the data.
Unfortunately, the process keeps growing in size and then the system crashes
when it can't get anymore memory.

Attached is a code sigment that show the the problem.  All it does is open up
/dev/udp, bind()'s to it and then loops doing a t_alloc() and t_free().
If you keep doing a ps(1) of the process, you will see that it keeps growing.

Does anyone know if this is a known bug in Interactive?
Do other vendor's System V have this bug?
or am I messing something fundimental?

-Kevin

------------------------------------------------------------------------
Kevin J. Dunlap                                      kjd@icxn.icxn.com
InterConnections, Inc.                               uunet!icxn!kjd
14711 NE 29th Place, Bellevue, WA  98007             206/881-5773

------------------ remove this line and everything above -------
/*
 *   Test program to show problem with using TLI t_free()
 *
 *   Compile:  cc -o test test.c -lnsl_s -lmalloc
 */


/* TLI Related Header Files */
#include <sys/tiuser.h>
#include <fcntl.h>
#include <stropts.h>
#include <sys/types.h>
#include <sys/bsdtypes.h>
#include <sys/socket.h>
#include <sys/stream.h>

#include <netinet/in.h>
#include <net/if.h>
#include <stdio.h>
#include <errno.h>

struct packet {
   u_char  type;
   u_char  seq;
   char    version;
   char    req;
};


int    fd;

struct t_unitdata   *unitdata;

extern int errno;
extern int t_errno;

main(argc, argv, envp)
int argc;
char *argv[], *envp[];
{
   int x;
   struct t_bind       *tes_bind;
   struct t_bind       *bind;
   struct t_unitdata   *tes_unitdata;
   struct sockaddr_in  address;
   struct packet       *data;

   /*
     * Create the transport endpoint.
     */

   if ((fd = t_open("/dev/udp", O_RDWR, NULL)) < 0) {
      perror("t_open can not open device");
      exit(1);
   }

   if ((bind = (struct t_bind *)t_alloc(fd, T_BIND, T_ALL)) == NULL) {
      t_error("t_alloc failed");
      exit(1);
   }
   bind->qlen = 0;

   bind->addr.len = sizeof(address);
   address.sin_family = AF_INET;
   address.sin_addr.s_addr = INADDR_ANY;
   address.sin_port = 61761;

   bind->addr.buf = (char *) &address;

   if (t_bind(fd, bind, bind) < 0) {
      t_error("t_bind for TES failed");
      exit(2);
   }
   for (x=0; x < 100000; x++) {
      if ((unitdata =(struct t_unitdata *)t_alloc(fd,T_UNITDATA,T_ALL))==NULL) {
         t_error("t_alloc failed");
         exit(2);
      }

      if ((data = (struct packet *) malloc(sizeof(struct packet))) == NULL) {
         perror("malloc failed");
         exit(2);
      }

      unitdata->opt.len = 0;
      unitdata->opt.buf = (char *)NULL;

      unitdata->udata.len = sizeof(*data);
      unitdata->udata.buf = (char *)data;

      /* the t_free() man page says next line isn't needed */
      free(unitdata->udata.buf);/* the t_free() 

      if (t_free(unitdata, T_UNITDATA) < 0) {
         t_error("t_free failed");
         exit(2);
      }
   }
}


-- 
------------------------------------------------------------------------
Kevin J. Dunlap                                      kjd@icxn.icxn.com
InterConnections, Inc.                               uunet!icxn!kjd
14711 NE 29th Place, Bellevue, WA  98007             206/881-5773

marc@dumbcat.sf.ca.us (Marco S Hyman) (05/20/91)

In article <142@icxn.UUCP> kjd@icxn.UUCP (Kevin J. Dunlap) writes:
 > I am having a problem with memory and using AT&T's TLI running on
 > Interactive 386/ix System V 3.2.2.  I have the updates to TCP/IP
 > installed (SSU.4a).

I see your problem.  Look at the man page for t_alloc again. I quote:

   "This function will allocate memory for the specified structure, and
   will also allocate memory for buffers referenced by the structure."

Your t_alloc call

  if ((unitdata =(struct t_unitdata *)t_alloc(fd,T_UNITDATA,T_ALL))==NULL) {

allocates both the t_unitdata structure but also all (T_ALL) fields in the
structure.  The maxlen field will be initialized for each buffer.  Later when
you do

  unitdata->opt.len = 0;
  unitdata->opt.buf = (char *)NULL;

  unitdata->udata.len = sizeof(*data);
  unitdata->udata.buf = (char *)data;

You overwrite the pointers that t_alloc built.  That memory is lost forever.
t_open and t_getinfo will give you the various lengths.   If you want to set
your own lengths use T_ADDR instead of T_ALL in the t_alloc call.  That's all
you wanted to allocate in your example.

// marc
-- 
// home: marc@dumbcat.sf.ca.us		pacbell!dumbcat!marc
// work: marc@ascend.com		uunet!aria!marc