tools/trace-malloc/leakstats.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  *
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include <stdio.h>
     7 #include <stdlib.h>
     8 #include <string.h>
     9 #include <errno.h>
    10 #ifdef HAVE_GETOPT_H
    11 #include <getopt.h>
    12 #else
    13 extern int  getopt(int argc, char *const *argv, const char *shortopts);
    14 extern char *optarg;
    15 extern int  optind;
    16 #ifdef XP_WIN32
    17 int optind=1;
    18 #endif
    19 #endif
    20 #include <time.h>
    21 #include "nsTraceMalloc.h"
    22 #include "tmreader.h"
    23 #include "prlog.h"
    25 static char *program;
    27 typedef struct handler_data {
    28     uint32_t current_heapsize;
    29     uint32_t max_heapsize;
    30     uint32_t bytes_allocated;
    31     uint32_t current_allocations;
    32     uint32_t total_allocations;
    33     uint32_t unmatched_frees;
    34     int finished;
    35 } handler_data;
    37 static void handler_data_init(handler_data *data)
    38 {
    39     data->current_heapsize = 0;
    40     data->max_heapsize = 0;
    41     data->bytes_allocated = 0;
    42     data->current_allocations = 0;
    43     data->total_allocations = 0;
    44     data->unmatched_frees = 0;
    45     data->finished = 0;
    46 }
    48 static void handler_data_finish(handler_data *data)
    49 {
    50 }
    52 static void my_tmevent_handler(tmreader *tmr, tmevent *event)
    53 {
    54     handler_data *data = (handler_data*) tmr->data;
    56     switch (event->type) {
    57       case TM_EVENT_REALLOC:
    58         /* On Windows, original allocation could be before we overrode malloc */
    59         if (event->u.alloc.oldserial != 0) {
    60           data->current_heapsize -= event->u.alloc.oldsize;
    61           --data->current_allocations;
    62         } else {
    63           ++data->unmatched_frees;
    64           PR_ASSERT(event->u.alloc.oldsize == 0);
    65         }
    66         /* fall-through intentional */
    67       case TM_EVENT_MALLOC:
    68       case TM_EVENT_CALLOC:
    69         ++data->current_allocations;
    70         ++data->total_allocations;
    71         data->bytes_allocated += event->u.alloc.size;
    72         data->current_heapsize += event->u.alloc.size;
    73         if (data->current_heapsize > data->max_heapsize)
    74             data->max_heapsize = data->current_heapsize;
    75         break;
    76       case TM_EVENT_FREE:
    77         /* On Windows, original allocation could be before we overrode malloc */
    78         if (event->serial != 0) {
    79           --data->current_allocations;
    80           data->current_heapsize -= event->u.alloc.size;
    81         } else {
    82           ++data->unmatched_frees;
    83           PR_ASSERT(event->u.alloc.size == 0);
    84         }
    85         break;
    86       case TM_EVENT_STATS:
    87         data->finished = 1;
    88         break;
    89     }
    90 }
    93 int main(int argc, char **argv)
    94 {
    95     int i, j, rv;
    96     tmreader *tmr;
    97     FILE *fp;
    98     time_t start;
    99     handler_data data;
   101     program = *argv;
   103     handler_data_init(&data);
   104     tmr = tmreader_new(program, &data);
   105     if (!tmr) {
   106         perror(program);
   107         exit(1);
   108     }
   110     start = time(NULL);
   111     fprintf(stdout, "%s starting at %s", program, ctime(&start));
   112     fflush(stdout);
   114     argc -= optind;
   115     argv += optind;
   116     if (argc == 0) {
   117         if (tmreader_eventloop(tmr, "-", my_tmevent_handler) <= 0)
   118             exit(1);
   119     } else {
   120         for (i = j = 0; i < argc; i++) {
   121             fp = fopen(argv[i], "r");
   122             if (!fp) {
   123                 fprintf(stderr,
   124                         "TEST-UNEXPECTED-FAIL | leakstats | can't open %s: %s\n",
   125                         argv[i], strerror(errno));
   126                 exit(1);
   127             }
   128             rv = tmreader_eventloop(tmr, argv[i], my_tmevent_handler);
   129             if (rv < 0)
   130                 exit(1);
   131             if (rv > 0)
   132                 j++;
   133             fclose(fp);
   134         }
   135         if (j == 0)
   136             exit(1);
   137     }
   139     if (!data.finished) {
   140         fprintf(stderr, "TEST-UNEXPECTED-FAIL | leakstats | log file incomplete\n");
   141         exit(1);
   142     }
   144     fprintf(stdout,
   145             "Leaks: %u bytes, %u allocations\n"
   146             "Maximum Heap Size: %u bytes\n"
   147             "%u bytes were allocated in %u allocations.\n",
   148             data.current_heapsize, data.current_allocations,
   149             data.max_heapsize,
   150             data.bytes_allocated, data.total_allocations);
   151     if (data.unmatched_frees != 0)
   152         fprintf(stdout,
   153                 "Logged %u free (or realloc) calls for which we missed the "
   154                 "original malloc.\n",
   155                 data.unmatched_frees);
   157     handler_data_finish(&data);
   158     tmreader_destroy(tmr);
   160     exit(0);
   161 }

mercurial