chiark / gitweb /
+ * Many memory leaks fixed.
authorian <ian>
Tue, 2 Nov 1999 23:40:14 +0000 (23:40 +0000)
committerian <ian>
Tue, 2 Nov 1999 23:40:14 +0000 (23:40 +0000)
@@ -4,14 +4,15 @@
   * Do not fail assertion if _qf_owner, _qf_search, domain ends in `.'.
   * Avoid infinite timeouts, causing lockup, when they should be zero !
   * TCP handling revamped (avoids recursive-invocation problems).
-  * Two memory leaks (one in all queries, one in cancelled ones) fixed.
+  * Many memory leaks fixed.

   Test and client program bug and portability fixes:
   * Dynamic library building works properly.
   * adnshost prints somewhat better messages about some wrong usages.
   * Include <stdlib.h> and <sys/types.h> in adnshost.h.
   * adnslogres: parsing and error checking improved (Tony Finch).
-  * Regresion tests can cope with zero-length reads.
+  * Regression tests can cope with zero-length reads.
+  * Regression tests check for memory leaks.

   General improvements
   * New adns_if_logpid option (functionality suggested by Tony Finch).

12 files changed:
changelog
client/adnstest.c
regress/Makefile.in
regress/case-flags10.sys
regress/harness.h.m4
regress/hcommon.c.m4
regress/hplayback.c.m4
regress/hrecord.c.m4
src/general.c
src/query.c
src/setup.c
src/transmit.c

index 2f292b1..2981a07 100644 (file)
--- a/changelog
+++ b/changelog
@@ -4,14 +4,15 @@ adns (0.6) unstable; urgency=high
   * Do not fail assertion if _qf_owner, _qf_search, domain ends in `.'.
   * Avoid infinite timeouts, causing lockup, when they should be zero !
   * TCP handling revamped (avoids recursive-invocation problems).
-  * Two memory leaks (one in all queries, one in cancelled ones) fixed.
+  * Many memory leaks fixed.
 
   Test and client program bug and portability fixes:
   * Dynamic library building works properly.
   * adnshost prints somewhat better messages about some wrong usages.
   * Include <stdlib.h> and <sys/types.h> in adnshost.h.
   * adnslogres: parsing and error checking improved (Tony Finch).
-  * Regresion tests can cope with zero-length reads.
+  * Regression tests can cope with zero-length reads.
+  * Regression tests check for memory leaks.
 
   General improvements
   * New adns_if_logpid option (functionality suggested by Tony Finch).
index 4abd4ff..2460dbf 100644 (file)
 # define OUTPUTSTREAM stdout
 #endif
 
+struct myctx {
+  adns_query qu;
+  int doneyet, found;
+  const char *fdom;
+};
+  
+static struct myctx *mcs;
+static adns_state ads;
+static adns_rrtype *types_a;
+
+static void quitnow(int rc) NONRETURNING;
+static void quitnow(int rc) {
+  free(mcs);
+  free(types_a);
+  if (ads) adns_finish(ads);
+  
+  exit(rc);
+}
+
 #ifndef HAVE_POLL
 #undef poll
 int poll(struct pollfd *ufds, int nfds, int timeout) {
   fputs("poll(2) not supported on this system\n",stderr);
-  exit(5);
+  quitnow(5);
 }
 #define adns_beforepoll(a,b,c,d,e) 0
 #define adns_afterpoll(a,b,c,d) 0
@@ -54,13 +73,13 @@ int poll(struct pollfd *ufds, int nfds, int timeout) {
 static void failure_status(const char *what, adns_status st) NONRETURNING;
 static void failure_status(const char *what, adns_status st) {
   fprintf(stderr,"adns failure: %s: %s\n",what,adns_strerror(st));
-  exit(2);
+  quitnow(2);
 }
 
 static void failure_errno(const char *what, int errnoval) NONRETURNING;
 static void failure_errno(const char *what, int errnoval) {
   fprintf(stderr,"adns failure: %s: errno=%d\n",what,errnoval);
-  exit(2);
+  quitnow(2);
 }
 
 static void usageerr(const char *why) NONRETURNING;
@@ -80,7 +99,7 @@ static void usageerr(const char *why) {
          "              4 usage error\n"
          "              5 operation not supported on this system\n",
          why);
-  exit(4);
+  quitnow(4);
 }
 
 static const adns_rrtype defaulttypes[]= {
@@ -120,7 +139,7 @@ static void fdom_split(const char *fdom, const char **dom_r, int *qf_r,
   if (*ep == ',' && strchr(ep,'/')) {
     ep++;
     while (*ep != '/') {
-      if (--ownflags_l <= 0) { fputs("too many flags\n",stderr); exit(3); }
+      if (--ownflags_l <= 0) { fputs("too many flags\n",stderr); quitnow(3); }
       *ownflags++= *ep++;
     }
   }
@@ -134,15 +153,8 @@ static int consistsof(const char *string, const char *accept) {
 }
 
 int main(int argc, char *const *argv) {
-  struct myctx {
-    adns_query qu;
-    int doneyet, found;
-    const char *fdom;
-  };
-  
-  adns_state ads;
   adns_query qu;
-  struct myctx *mcs, *mc, *mcw;
+  struct myctx *mc, *mcw;
   void *mcr;
   adns_answer *ans;
   const char *initstring, *rrtn, *fmtn;
@@ -153,7 +165,6 @@ int main(int argc, char *const *argv) {
   int r;
   const adns_rrtype *types;
   struct timeval now;
-  adns_rrtype *types_a;
   char ownflags[10];
   char *ep;
   const char *initflags, *owninitflags;
@@ -185,7 +196,7 @@ int main(int argc, char *const *argv) {
     for (cp= argv[1]+1, tc=1; (ch= *cp); cp++)
       if (ch==',') tc++;
     types_a= malloc(sizeof(*types_a)*(tc+1));
-    if (!types_a) { perror("malloc types"); exit(3); }
+    if (!types_a) { perror("malloc types"); quitnow(3); }
     for (cp= argv[1]+1, ti=0; ti<tc; ti++) {
       types_a[ti]= strtoul(cp,&cp,10);
       if ((ch= *cp)) {
@@ -193,10 +204,11 @@ int main(int argc, char *const *argv) {
        cp++;
       }
     }
-    *cp++= adns_r_none;
+    types_a[ti]= adns_r_none;
     types= types_a;
     argv++;
   } else {
+    types_a= 0;
     types= defaulttypes;
   }
   
@@ -205,8 +217,8 @@ int main(int argc, char *const *argv) {
 
   for (qc=0; fdomlist[qc]; qc++);
   for (tc=0; types[tc] != adns_r_none; tc++);
-  mcs= malloc(sizeof(*mcs)*qc*tc);
-  if (!mcs) { perror("malloc mcs"); exit(3); }
+  mcs= malloc(tc ? sizeof(*mcs)*qc*tc : 1);
+  if (!mcs) { perror("malloc mcs"); quitnow(3); }
 
   if (initstring) {
     r= adns_init_strcfg(&ads,
@@ -293,7 +305,7 @@ int main(int argc, char *const *argv) {
     
     fdom_split(mc->fdom,&domain,&qflags,ownflags,sizeof(ownflags));
 
-    if (gettimeofday(&now,0)) { perror("gettimeofday"); exit(3); }
+    if (gettimeofday(&now,0)) { perror("gettimeofday"); quitnow(3); }
       
     ri= adns_rr_info(ans->type, &rrtn,&fmtn,&len, 0,0);
     fprintf(stdout, "%s flags %d type ",domain,qflags);
@@ -321,8 +333,5 @@ int main(int argc, char *const *argv) {
     mc->doneyet= 1;
   }
 
-  free(mcs);
-  adns_finish(ads);
-  
-  exit(0);
+  quitnow(0);
 }
index 3ed85f1..2945c8b 100644 (file)
@@ -35,6 +35,7 @@ HCPPFLAGS:= $(foreach F,                      \
        gettimeofday select poll                \
        socket fcntl connect close              \
        sendto recvfrom read write writev       \
+       malloc realloc free exit                \
 , -D$F=H$F)
 
 HARNLOBJS=     $(addsuffix _d.o, $(basename $(LIBOBJS)))
index 550bc22..c535edd 100644 (file)
@@ -10,3 +10,6 @@ default
  fcntl fd=4 cmd=F_SETFL O_NONBLOCK|...
  fcntl=OK
  +0.000061
+ close fd=4
+ close=OK
+ +0.000001
index 12ecc3e..35efa18 100644 (file)
@@ -48,6 +48,11 @@ m4_include(`hsyscalls.i4')
 int Hwritev(int fd, const struct iovec *vector, size_t count);
 int Hgettimeofday(struct timeval *tv, struct timezone *tz);
 
+void *Hmalloc(size_t sz);
+void Hfree(void *ptr);
+void *Hrealloc(void *op, size_t nsz);
+void Hexit(int rv);
+
 /* There is a Q function (Q for Question) for each such syscall;
  * it constructs a string representing the call, and calls Q_str
  * on it, or constructs it in vb and calls Q_vb;
@@ -59,6 +64,8 @@ m4_include(`hsyscalls.i4')
 
 void Q_vb(void);
 
+extern void Tshutdown(void);
+
 /* General help functions */
 
 void Tfailed(const char *why);
index 59d97ed..311087e 100644 (file)
@@ -28,6 +28,7 @@ m4_include(hmacros.i4)
 #include <fcntl.h>
 #include <string.h>
 #include <errno.h>
+#include <stdlib.h>
 
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -228,3 +229,80 @@ void Tnomem(void) {
 void Toutputerr(void) {
   Tfailed("write error on test harness output");
 }
+
+struct malloced {
+  struct malloced *next, *back;
+  size_t sz;
+  unsigned long count;
+  struct { double d; long ul; void *p; void (*fp)(void); } data;
+};
+
+static unsigned long malloccount, mallocfailat;
+static struct { struct malloced *head, *tail; } mallocedlist;
+
+#define MALLOCHSZ ((char*)&mallocedlist.head->data - (char*)mallocedlist.head)
+
+void *Hmalloc(size_t sz) {
+  struct malloced *newnode;
+  const char *mfavar;
+  char *ep;
+
+  assert(sz);
+
+  newnode= malloc(MALLOCHSZ + sz);  if (!newnode) Tnomem();
+
+  LIST_LINK_TAIL(mallocedlist,newnode);
+  newnode->sz= sz;
+  newnode->count= ++malloccount;
+  if (!mallocfailat) {
+    mfavar= getenv("ADNS_REGRESS_MALLOCFAILAT");
+    if (mfavar) {
+      mallocfailat= strtoul(mfavar,&ep,10);
+      if (!mallocfailat || *ep) Tfailed("ADNS_REGRESS_MALLOCFAILAT bad value");
+    } else {
+      mallocfailat= ~0UL;
+    }
+  }
+  assert(newnode->count != mallocfailat);
+  memset(&newnode->data,0xc7,sz);
+  return &newnode->data;
+}
+
+void Hfree(void *ptr) {
+  struct malloced *oldnode;
+
+  if (!ptr) return;
+
+  oldnode= (void*)((char*)ptr - MALLOCHSZ);
+  LIST_UNLINK(mallocedlist,oldnode);
+  memset(&oldnode->data,0x38,oldnode->sz);
+  free(oldnode);
+}
+
+void *Hrealloc(void *op, size_t nsz) {
+  struct malloced *oldnode;
+  void *np;
+  size_t osz;
+
+  if (op) { oldnode= (void*)((char*)op - MALLOCHSZ); osz= oldnode->sz; } else { osz= 0; }
+  np= Hmalloc(nsz);
+  memcpy(np,op, osz>nsz ? nsz : osz);
+  Hfree(op);
+  return np;
+}
+
+void Hexit(int rv) {
+  struct malloced *loopnode;
+
+  Tshutdown();
+  adns__vbuf_free(&vb);
+  adns__vbuf_free(&vbw);
+  if (mallocedlist.head) {
+    fprintf(stderr,"adns test harness: memory leaked:");
+    for (loopnode=mallocedlist.head; loopnode; loopnode=loopnode->next)
+      fprintf(stderr," %lu(%lu)",loopnode->count,(unsigned long)loopnode->sz);
+    putc('\n',stderr);
+    if (ferror(stderr)) exit(-1);
+  }
+  exit(rv);
+}
index d7b383a..97e951a 100644 (file)
@@ -40,6 +40,10 @@ m4_include(hmacros.i4)
 static FILE *Tinputfile, *Treportfile;
 static vbuf vb2;
 
+extern void Tshutdown(void) {
+  adns__vbuf_free(&vb2);
+}
+
 static void Tensurereportfile(void) {
   const char *fdstr;
   int fd;
index 1e98c82..c6417ca 100644 (file)
@@ -35,6 +35,9 @@ m4_include(hmacros.i4)
 
 static FILE *Toutputfile;
 
+void Tshutdown(void) {
+}
+
 static void R_recordtime(void) {
   int r;
   struct timeval tv, tvrel;
index 0168a4a..8793762 100644 (file)
@@ -68,6 +68,7 @@ void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
     if (qu->typei && qu->typei->fmtname)
       fprintf(ads->diagfile,"(%s)",qu->typei->fmtname);
     bef=", "; aft=")\n";
+    adns__vbuf_free(&vb);
   }
   
   if (serv>=0) {
index e6bc7a0..37306d1 100644 (file)
@@ -91,7 +91,7 @@ static void query_submit(adns_state ads, adns_query qu,
                         const typeinfo *typei, vbuf *qumsg_vb, int id,
                         adns_queryflags flags, struct timeval now) {
   /* Fills in the query message in for a previously-allocated query,
-   * and submits it.  Cannot fail.
+   * and submits it.  Cannot fail.  Takes over the memory for qumsg_vb.
    */
 
   qu->vb= *qumsg_vb;
@@ -131,7 +131,7 @@ static void query_simple(adns_state ads, adns_query qu,
   int id;
   adns_status stat;
 
-  adns__vbuf_init(&vb);
+  vb= qu->vb;
   
   stat= adns__mkquery(ads,&vb,&id, owner,ol, typei,flags);
   if (stat) { adns__query_fail(qu,stat); return; }
@@ -390,6 +390,7 @@ static void free_query_allocs(adns_query qu) {
   for (an= qu->allocations.head; an; an= ann) { ann= an->next; free(an); }
   LIST_INIT(qu->allocations);
   adns__vbuf_free(&qu->vb);
+  adns__vbuf_free(&qu->search_vb);
   free(qu->query_dgram);
 }
 
index dca8a19..e19a705 100644 (file)
@@ -62,6 +62,11 @@ static void addserver(adns_state ads, struct in_addr addr) {
   ads->nservers++;
 }
 
+static void freesearchlist(adns_state ads) {
+  if (ads->nsearchlist) free(*ads->searchlist);
+  free(ads->searchlist);
+}
+
 static void saveerr(adns_state ads, int en) {
   if (!ads->configerrno) ads->configerrno= en;
 }
@@ -133,7 +138,7 @@ static void ccf_search(adns_state ads, const char *fn, int lno, const char *buf)
     *newchars++ = 0;
   }
 
-  free(ads->searchlist);
+  freesearchlist(ads);
   ads->nsearchlist= count;
   ads->searchlist= newptrs;
 }
@@ -591,6 +596,7 @@ void adns_finish(adns_state ads) {
   if (ads->tcpsocket >= 0) close(ads->tcpsocket);
   adns__vbuf_free(&ads->tcpsend);
   adns__vbuf_free(&ads->tcprecv);
+  freesearchlist(ads);
   free(ads);
 }
 
index edb79c3..c5ae9dc 100644 (file)
@@ -81,7 +81,7 @@ adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r,
   const char *p, *pe;
   adns_status st;
 
-  st= mkquery_header(ads,vb,id_r,strlen(owner)+2); if (st) return st;
+  st= mkquery_header(ads,vb,id_r,ol+2); if (st) return st;
   
   MKQUERY_START(vb);