]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/smartall.c
Add pool memory debug output
[bacula/bacula] / bacula / src / lib / smartall.c
index 9ebfbbb13c437c4e574043f28fe33f0ecf99fae2..db2066d0e57a883a3e7fb4d3d1634a1e7f34f4ca 100644 (file)
@@ -1,12 +1,12 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
    This program is Free Software; you can redistribute it and/or
-   modify it under the terms of version two of the GNU General Public
+   modify it under the terms of version three of the GNU Affero General Public
    License as published by the Free Software Foundation and included
    in the file LICENSE.
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.
 
-   You should have received a copy of the GNU General Public License
+   You should have received a copy of the GNU Affero General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Bacula® is a registered trademark of John Walker.
+   Bacula® is a registered trademark of Kern Sibbald.
    The licensor of Bacula is the Free Software Foundation Europe
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 
                   http://www.fourmilab.ch/smartall/
 
-
-         Version $Id$
-
 */
 
+#define _LOCKMGR_COMPLIANT
+
 #include "bacula.h"
 /* Use the real routines here */
 #undef realloc
@@ -56,6 +55,7 @@
  *  If you want it, simply #ifdef all the
  *  following off.
  */
+#ifdef no_debug_xxxxx
 #undef Dmsg1
 #undef Dmsg2
 #undef Dmsg3
@@ -64,6 +64,7 @@
 #define Dmsg2(l,f,a1,a2)
 #define Dmsg3(l,f,a1,a2,a3)
 #define Dmsg4(l,f,a1,a2,a3,a4)
+#endif
 
 
 uint64_t sm_max_bytes = 0;
@@ -77,8 +78,6 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 
 extern char my_name[];                /* daemon name */
 
-typedef unsigned short sm_ushort;
-
 #define EOS      '\0'              /* End of string sentinel */
 #define sm_min(a, b) ((a) < (b) ? (a) : (b))
 
@@ -88,9 +87,9 @@ typedef unsigned short sm_ushort;
 
 struct abufhead {
    struct b_queue abq;         /* Links on allocated queue */
-   unsigned ablen;             /* Buffer length in bytes */
+   uint32_t ablen;             /* Buffer length in bytes */
    const char *abfname;        /* File name pointer */
-   sm_ushort ablineno;         /* Line number of allocation */
+   uint32_t ablineno;          /* Line number of allocation */
    bool abin_use;              /* set when malloced and cleared when free */
 };
 
@@ -129,10 +128,10 @@ static void *smalloc(const char *fname, int lineno, unsigned int nbytes)
       qinsert(&abqueue, (struct b_queue *) buf);
       head->ablen = nbytes;
       head->abfname = bufimode ? NULL : fname;
-      head->ablineno = (sm_ushort)lineno;
+      head->ablineno = (uint32_t)lineno;
       head->abin_use = true;
       /* Emplace end-clobber detector at end of buffer */
-      buf[nbytes - 1] = (uint8_t)((((long) buf) & 0xFF) ^ 0xC5);
+      buf[nbytes - 1] = (uint8_t)((((intptr_t) buf) & 0xFF) ^ 0xC5);
       buf += HEAD_SIZE;  /* Increment to user data start */
       if (++sm_buffers > sm_max_buffers) {
          sm_max_buffers = sm_buffers;
@@ -145,7 +144,7 @@ static void *smalloc(const char *fname, int lineno, unsigned int nbytes)
    } else {
       Emsg0(M_ABORT, 0, _("Out of memory\n"));
    }
-   Dmsg4(1150, "smalloc %d at %x from %s:%d\n", nbytes, buf, fname, lineno);
+   Dmsg4(1150, "smalloc %d at %p from %s:%d\n", nbytes, buf, fname, lineno);
 #if    SMALLOC_SANITY_CHECK > 0
    if (sm_bytes > SMALLOC_SANITY_CHECK) {
       Emsg0(M_ABORT, 0, _("Too much memory used."));
@@ -161,7 +160,7 @@ void sm_new_owner(const char *fname, int lineno, char *buf)
 {
    buf -= HEAD_SIZE;  /* Decrement to header */
    ((struct abufhead *)buf)->abfname = bufimode ? NULL : fname;
-   ((struct abufhead *)buf)->ablineno = (sm_ushort) lineno;
+   ((struct abufhead *)buf)->ablineno = (uint32_t) lineno;
    ((struct abufhead *)buf)->abin_use = true;
    return;
 }
@@ -175,9 +174,10 @@ void sm_free(const char *file, int line, void *fp)
 {
    char *cp = (char *) fp;
    struct b_queue *qp;
+   uint32_t lineno = line;
 
    if (cp == NULL) {
-      Emsg2(M_ABORT, 0, _("Attempt to free NULL called from %s:%d\n"), file, line);
+      Emsg2(M_ABORT, 0, _("Attempt to free NULL called from %s:%d\n"), file, lineno);
    }
 
    cp -= HEAD_SIZE;
@@ -185,13 +185,13 @@ void sm_free(const char *file, int line, void *fp)
    struct abufhead *head = (struct abufhead *)cp;
 
    P(mutex);
-   Dmsg4(1150, "sm_free %d at %x from %s:%d\n",
+   Dmsg4(1150, "sm_free %d at %p from %s:%d\n",
          head->ablen, fp,
          head->abfname, head->ablineno);
 
    if (!head->abin_use) {
       V(mutex);
-      Emsg2(M_ABORT, 0, _("double free from %s:%d\n"), file, line);
+      Emsg2(M_ABORT, 0, _("double free from %s:%d\n"), file, lineno);
    }
    head->abin_use = false;
 
@@ -199,19 +199,22 @@ void sm_free(const char *file, int line, void *fp)
       of an address which isn't an allocated buffer. */
    if (qp->qnext->qprev != qp) {
       V(mutex);
-      Emsg2(M_ABORT, 0, _("qp->qnext->qprev != qp called from %s:%d\n"), file, line);
+      Emsg2(M_ABORT, 0, _("qp->qnext->qprev != qp called from %s:%d\n"), file, lineno);
    }
    if (qp->qprev->qnext != qp) {
       V(mutex);
-      Emsg2(M_ABORT, 0, _("qp->qprev->qnext != qp called from %s:%d\n"), file, line);
+      Emsg2(M_ABORT, 0, _("qp->qprev->qnext != qp called from %s:%d\n"), file, lineno);
    }
 
    /* The following assertion detects storing off the  end  of  the
       allocated  space in the buffer by comparing the end of buffer
       checksum with the address of the buffer.  */
 
-   if (((unsigned char *)cp)[head->ablen - 1] != ((((long) cp) & 0xFF) ^ 0xC5)) {
+   if (((unsigned char *)cp)[head->ablen - 1] != ((((intptr_t) cp) & 0xFF) ^ 0xC5)) {
       V(mutex);
+      Dmsg4(0, "Overrun buffer: len=%d addr=%p allocated: %s:%d\n",
+         head->ablen, fp,
+         head->abfname, head->ablineno);
       Emsg2(M_ABORT, 0, _("Buffer overrun called from %s:%d\n"), file, line);
    }
    if (sm_buffers > 0) {
@@ -287,7 +290,7 @@ void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size)
    void *buf;
    char *cp = (char *) ptr;
 
-   Dmsg4(400, "sm_realloc %s:%d 0x%x %d\n", fname, lineno, ptr, size);
+   Dmsg4(1400, "sm_realloc %s:%d %p %d\n", fname, (uint32_t)lineno, ptr, size);
    if (size <= 0) {
       e_msg(fname, lineno, M_ABORT, 0, _("sm_realloc size: %d\n"), size);
    }
@@ -325,9 +328,9 @@ void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size)
       }
 
       /* All done.  Free and dechain the original buffer. */
-      sm_free(__FILE__, __LINE__, ptr);
+      sm_free(fname, lineno, ptr);
    }
-   Dmsg4(150, _("sm_realloc %d at %x from %s:%d\n"), size, buf, fname, lineno);
+   Dmsg4(4150, _("sm_realloc %d at %p from %s:%d\n"), size, buf, fname, (uint32_t)lineno);
    return buf;
 }
 
@@ -358,7 +361,7 @@ void *actuallycalloc(unsigned int nelem, unsigned int elsize)
 
 void *actuallyrealloc(void *ptr, unsigned int size)
 {
-   Dmsg2(400, "Actuallyrealloc 0x%x %d\n", ptr, size);
+   Dmsg2(1400, "Actuallyrealloc %p %d\n", ptr, size);
    return realloc(ptr, size);
 }
 
@@ -372,8 +375,6 @@ void actuallyfree(void *cp)
 
 /*  SM_DUMP  --  Print orphaned buffers (and dump them if BUFDUMP is
  *               True).
- *  N.B. DO NOT USE any Bacula print routines (Dmsg, Jmsg, Emsg, ...)
- *    as they have all been shut down at this point.
  */
 void sm_dump(bool bufdump, bool in_use) 
 {
@@ -388,7 +389,7 @@ void sm_dump(bool bufdump, bool in_use)
       if ((ap == NULL) ||
           (ap->abq.qnext->qprev != (struct b_queue *) ap) ||
           (ap->abq.qprev->qnext != (struct b_queue *) ap)) {
-         fprintf(stderr, _(
+         Pmsg1(0, _(
             "\nOrphaned buffers exist.  Dump terminated following\n"
             "  discovery of bad links in chain of orphaned buffers.\n"
             "  Buffer address with bad links: %p\n"), ap);
@@ -396,16 +397,13 @@ void sm_dump(bool bufdump, bool in_use)
       }
 
       if (ap->abfname != NULL) {
-         unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
          char errmsg[500];
+         uint32_t memsize = ap->ablen - (HEAD_SIZE + 1);
          char *cp = ((char *)ap) + HEAD_SIZE;
 
-         bsnprintf(errmsg, sizeof(errmsg),
-           _("%s buffer:  %s %6u bytes buf=%p allocated at %s:%d\n"),
+         Pmsg6(0, "%s buffer: %s %d bytes at %p from %s:%d\n", 
             in_use?"In use":"Orphaned",
-            my_name, memsize, cp, ap->abfname, ap->ablineno
-         );
-         fprintf(stderr, "%s", errmsg);
+            my_name, memsize, cp, ap->abfname, ap->ablineno);
          if (bufdump) {
             char buf[20];
             unsigned llen = 0;
@@ -415,7 +413,7 @@ void sm_dump(bool bufdump, bool in_use)
                if (llen >= 16) {
                   bstrncat(errmsg, "\n", sizeof(errmsg));
                   llen = 0;
-                  fprintf(stderr, "%s", errmsg);
+                  Pmsg1(0, "%s", errmsg);
                   errmsg[0] = EOS;
                }
                bsnprintf(buf, sizeof(buf), " %02X",
@@ -424,7 +422,7 @@ void sm_dump(bool bufdump, bool in_use)
                llen++;
                memsize--;
             }
-            fprintf(stderr, "%s\n", errmsg);
+            Pmsg1(0, "%s\n", errmsg);
          }
       }
       ap = (struct abufhead *) ap->abq.qnext;
@@ -438,7 +436,7 @@ void sm_check(const char *fname, int lineno, bool bufdump)
 {
    if (!sm_check_rtn(fname, lineno, bufdump)) {
       Emsg2(M_ABORT, 0, _("Damaged buffer found. Called from %s:%d\n"),
-            fname, lineno);
+            fname, (uint32_t)lineno);
    }
 }
 
@@ -451,41 +449,50 @@ int sm_check_rtn(const char *fname, int lineno, bool bufdump)
 
    P(mutex);
    ap = (struct abufhead *) abqueue.qnext;
-   while (ap != (struct abufhead *) &abqueue) {
+   while (ap != (struct abufhead *)&abqueue) {
       bad = 0;
-      if ((ap == NULL) ||
-          (ap->abq.qnext->qprev != (struct b_queue *) ap)) {
-         bad = 0x1;
-      }
-      if (ap->abq.qprev->qnext != (struct b_queue *) ap) {
-         bad |= 0x2;
-      }
-      if (((unsigned char *) ap)[((struct abufhead *) ap)->ablen - 1] !=
-           ((((long) ap) & 0xFF) ^ 0xC5)) {
-         bad |= 0x4;
+      if (ap != NULL) {
+         if (ap->abq.qnext->qprev != (struct b_queue *)ap) {
+            bad = 0x1;
+         }
+         if (ap->abq.qprev->qnext != (struct b_queue *)ap) {
+            bad |= 0x2;
+         }
+         if (((unsigned char *) ap)[((struct abufhead *)ap)->ablen - 1] !=
+              ((((intptr_t) ap) & 0xFF) ^ 0xC5)) {
+            bad |= 0x4;
+         }
+      } else {
+         bad = 0x8;
       }
       badbuf |= bad;
       if (bad) {
-         fprintf(stderr,
-            _("\nDamaged buffers found at %s:%d\n"), fname, lineno);
+         Pmsg2(0, 
+            _("\nDamaged buffers found at %s:%d\n"), fname, (uint32_t)lineno);
 
          if (bad & 0x1) {
-            fprintf(stderr, _("  discovery of bad prev link.\n"));
+            Pmsg0(0,  _("  discovery of bad prev link.\n"));
          }
          if (bad & 0x2) {
-            fprintf(stderr, _("  discovery of bad next link.\n"));
+            Pmsg0(0, _("  discovery of bad next link.\n"));
          }
          if (bad & 0x4) {
-            fprintf(stderr, _("  discovery of data overrun.\n"));
+            Pmsg0(0, _("  discovery of data overrun.\n"));
+         }
+         if (bad & 0x8) {
+            Pmsg0(0, _("  NULL pointer.\n"));
          }
 
-         fprintf(stderr, _("  Buffer address: %p\n"), ap);
+         if (!ap) {
+            goto get_out;
+         }
+         Pmsg1(0, _("  Buffer address: %p\n"), ap);
 
          if (ap->abfname != NULL) {
-            unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
+            uint32_t memsize = ap->ablen - (HEAD_SIZE + 1);
             char errmsg[80];
 
-            fprintf(stderr,
+            Pmsg4(0, 
               _("Damaged buffer:  %6u bytes allocated at line %d of %s %s\n"),
                memsize, ap->ablineno, my_name, ap->abfname
             );
@@ -498,7 +505,7 @@ int sm_check_rtn(const char *fname, int lineno, bool bufdump)
                   if (llen >= 16) {
                      strcat(errmsg, "\n");
                      llen = 0;
-                     fprintf(stderr, "%s", errmsg);
+                     Pmsg1(0, "%s", errmsg);
                      errmsg[0] = EOS;
                   }
                   if (*cp < 0x20) {
@@ -511,12 +518,13 @@ int sm_check_rtn(const char *fname, int lineno, bool bufdump)
                   llen++;
                   memsize--;
                }
-               fprintf(stderr, "%s\n", errmsg);
+               Pmsg1(0, "%s\n", errmsg);
             }
          }
       }
-      ap = (struct abufhead *) ap->abq.qnext;
+      ap = (struct abufhead *)ap->abq.qnext;
    }
+get_out:
    V(mutex);
    return badbuf ? 0 : 1;
 }
@@ -548,7 +556,7 @@ void * operator new(size_t size)
 
 void operator delete(void *buf)
 {
-// Dmsg1(000, "free called 0x%x\n", buf);
+// Dmsg1(000, "free called %p\n", buf);
    sm_free(__FILE__, __LINE__, buf);
 }
 #endif