Move trace-malloc readers from mozilla/xpcom/base/ to mozilla/tools/trace-malloc/. Add a --shutdown-leaks option to nsTraceMalloc to dump, to the file given as an argument to the option, information about allocations still live at shutdown. Add a new trace-malloc reader (leakstats.c) to print leak statistics. b=84831 r=jag sr=brendan

This commit is contained in:
dbaron%fas.harvard.edu 2001-09-08 18:29:24 +00:00
Родитель 025d54da07
Коммит 03b8e91855
10 изменённых файлов: 494 добавлений и 190 удалений

Просмотреть файл

@ -154,6 +154,10 @@ ifdef ENABLE_TESTS
DIRS += xpcom/tests
endif
ifdef NS_TRACE_MALLOC
DIRS += tools/trace-malloc
endif
DIRS += l10n
ifneq (,$(MOZ_STATIC_COMPONENTS)$(MOZ_META_COMPONENTS))

Просмотреть файл

@ -913,6 +913,11 @@ if [ "$MOZ_LEAKY" ]; then
MAKEFILES_leaky="tools/leaky/Makefile"
fi
# tools/trace-malloc
if [ "$NS_TRACE_MALLOC" ]; then
MAKEFILES_tracemalloc="tools/trace-malloc/Makefile"
fi
# layout/mathml
if [ "$MOZ_MATHML" ]; then
MAKEFILES_layout="$MAKEFILES_layout
@ -1123,6 +1128,7 @@ $MAKEFILES_rdf
$MAKEFILES_static_components
$MAKEFILES_sun_java
$MAKEFILES_themes
$MAKEFILES_tracemalloc
$MAKEFILES_uriloader
$MAKEFILES_view
$MAKEFILES_webshell

Просмотреть файл

@ -0,0 +1,47 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
REQUIRES = string xpcom
CSRCS += \
bloatblame.c \
leakstats.c \
$(NULL)
SIMPLE_PROGRAMS = $(CSRCS:.c=$(BIN_SUFFIX))
include $(topsrcdir)/config/config.mk
LIBS += \
$(NSPR_LIBS) \
tmreader.o \
$(NULL)
EXTRA_DEPS = tmreader.o
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,167 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsTraceMalloc.c/bloatblame.c code, released
* April 19, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Brendan Eich, 14-April-2000
* L. David Baron, 2001-06-07, created leakstats.c based on bloatblame.c
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the MPL or the GPL.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#else
extern int getopt(int argc, char *const *argv, const char *shortopts);
extern char *optarg;
extern int optind;
#endif
#include <time.h>
#include "nsTraceMalloc.h"
#include "tmreader.h"
static char *program;
typedef struct handler_data {
uint32 current_heapsize;
uint32 max_heapsize;
uint32 bytes_allocated;
uint32 current_allocations;
uint32 total_allocations;
int finished;
} handler_data;
static void handler_data_init(handler_data *data)
{
data->current_heapsize = 0;
data->max_heapsize = 0;
data->bytes_allocated = 0;
data->current_allocations = 0;
data->total_allocations = 0;
data->finished = 0;
}
static void handler_data_finish(handler_data *data)
{
}
static void my_tmevent_handler(tmreader *tmr, tmevent *event)
{
handler_data *data = (handler_data*) tmr->data;
switch (event->type) {
case TM_EVENT_REALLOC:
data->current_heapsize -= event->u.alloc.oldsize;
--data->current_allocations;
/* fall-through intentional */
case TM_EVENT_MALLOC:
case TM_EVENT_CALLOC:
++data->current_allocations;
++data->total_allocations;
data->bytes_allocated += event->u.alloc.size;
data->current_heapsize += event->u.alloc.size;
if (data->current_heapsize > data->max_heapsize)
data->max_heapsize = data->current_heapsize;
break;
case TM_EVENT_FREE:
--data->current_allocations;
data->current_heapsize -= event->u.alloc.size;
break;
case TM_EVENT_STATS:
data->finished = 1;
break;
}
}
int main(int argc, char **argv)
{
int c, i, j, rv;
tmreader *tmr;
FILE *fp;
time_t start;
handler_data data;
program = *argv;
handler_data_init(&data);
tmr = tmreader_new(program, &data);
if (!tmr) {
perror(program);
exit(1);
}
start = time(NULL);
fprintf(stdout, "%s starting at %s", program, ctime(&start));
fflush(stdout);
argc -= optind;
argv += optind;
if (argc == 0) {
if (tmreader_eventloop(tmr, "-", my_tmevent_handler) <= 0)
exit(1);
} else {
for (i = j = 0; i < argc; i++) {
fp = fopen(argv[i], "r");
if (!fp) {
fprintf(stderr, "%s: can't open %s: %s\n",
program, argv[i], strerror(errno));
exit(1);
}
rv = tmreader_eventloop(tmr, argv[i], my_tmevent_handler);
if (rv < 0)
exit(1);
if (rv > 0)
j++;
fclose(fp);
}
if (j == 0)
exit(1);
}
if (!data.finished) {
fprintf(stderr, "%s: log file incomplete\n", program);
exit(1);
}
fprintf(stdout,
"Leaks: %u bytes, %u allocations\n"
"Maximum Heap Size: %u bytes\n"
"%u bytes were allocated in %u allocations.\n",
data.current_heapsize, data.current_allocations,
data.max_heapsize,
data.bytes_allocated, data.total_allocations);
handler_data_finish(&data);
tmreader_destroy(tmr);
exit(0);
}

Просмотреть файл

@ -56,6 +56,7 @@
#include "prlog.h"
#include "prmon.h"
#include "prprf.h"
#include "prenv.h"
#include "nsTraceMalloc.h"
#ifdef XP_WIN32
@ -68,7 +69,7 @@
#define WRITE_FLAGS "w"
#endif //WIN32
#endif /* WIN32 */
#ifdef XP_UNIX
@ -268,6 +269,7 @@ static logfile *logfile_list = NULL;
static logfile **logfile_tail = &logfile_list;
static logfile *logfp = &default_logfile;
static PRMonitor *tmmon = NULL;
static char *sdlogname = NULL; /* filename for shutdown leak log */
/* We don't want more than 32 logfiles open at once, ok? */
typedef uint32 lfd_set;
@ -318,7 +320,7 @@ retry:
static void flush_logfile(logfile *fp)
{
int len, cnt;
int fd;
int fd;
char *bp;
len = fp->pos;
@ -570,15 +572,17 @@ static callsite *calltree(int skip)
if (! ok)
return 0;
// Get the context information for this thread. That way we will
// know where our sp, fp, pc, etc. are and can fill in the
// STACKFRAME with the initial values.
/*
* Get the context information for this thread. That way we will
* know where our sp, fp, pc, etc. are and can fill in the
* STACKFRAME with the initial values.
*/
context.ContextFlags = CONTEXT_FULL;
ok = GetThreadContext(myThread, &context);
if (! ok)
return 0;
// Setup initial stack frame to walk from
/* Setup initial stack frame to walk from */
memset(&(frame[0]), 0, sizeof(frame[0]));
frame[0].AddrPC.Offset = context.Eip;
frame[0].AddrPC.Mode = AddrModeFlat;
@ -598,10 +602,11 @@ static callsite *calltree(int skip)
myThread,
&(frame[framenum]),
&context,
0, // read process memory routine
_SymFunctionTableAccess, // function table access routine
_SymGetModuleBase, // module base routine
0); // translate address routine
0, /* read process memory routine */
_SymFunctionTableAccess, /* function table access
routine */
_SymGetModuleBase, /* module base routine */
0); /* translate address routine */
if (!ok) {
break;
@ -676,7 +681,7 @@ static callsite *calltree(int skip)
{
DWORD error = GetLastError();
PR_ASSERT(error);
library = "unknown";//ew
library = "unknown";/* ew */
}
else
{
@ -707,7 +712,7 @@ static callsite *calltree(int skip)
hash = PL_HashString(library);
hep = PL_HashTableRawLookup(libraries, hash, library);
he = *hep;
library = strdup(library); //strdup it always?
library = strdup(library); /* strdup it always? */
if (he) {
library_serial = (uint32) he->value;
le = (lfdset_entry *) he;
@ -716,7 +721,7 @@ static callsite *calltree(int skip)
le = NULL;
}
} else {
// library = strdup(library);
/* library = strdup(library); */
if (library) {
library_serial = ++library_serial_generator;
he = PL_HashTableRawAdd(libraries, hep, hash, library,
@ -1430,97 +1435,131 @@ PR_IMPLEMENT(void) NS_TraceMallocStartup(int logfd)
}
/*
* Options for log files, with the log file name either as the next option
* or separated by '=' (e.g. "./mozilla --trace-malloc * malloc.log" or
* "./mozilla --trace-malloc=malloc.log").
*/
static const char TMLOG_OPTION[] = "--trace-malloc";
static const char SDLOG_OPTION[] = "--shutdown-leaks";
#define SHOULD_PARSE_ARG(name_, log_, arg_) \
(0 == strncmp(arg_, name_, sizeof(name_) - 1))
#define PARSE_ARG(name_, log_, argv_, i_, consumed_) \
PR_BEGIN_MACRO \
char _nextchar = argv_[i_][sizeof(name_) - 1]; \
if (_nextchar == '=') { \
log_ = argv_[i_] + sizeof(name_); \
consumed_ = 1; \
} else if (_nextchar == '\0') { \
log_ = argv_[i_+1]; \
consumed_ = 2; \
} \
PR_END_MACRO
PR_IMPLEMENT(int) NS_TraceMallocStartupArgs(int argc, char* argv[])
{
int i, logfd = -1;
int i, logfd = -1, consumed;
char *tmlogname = NULL; /* note global |sdlogname| */
/*
* Look for the --trace-malloc <logfile> option early, to avoid missing
* early mallocs (we miss static constructors whose output overflows the
* log file's static 16K output buffer).
*/
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "--trace-malloc") == 0 && i < argc-1) {
char *logfilename;
int pipefds[2];
for (i = 1; i < argc; i += consumed) {
consumed = 0;
if (SHOULD_PARSE_ARG(TMLOG_OPTION, tmlogname, argv[i]))
PARSE_ARG(TMLOG_OPTION, tmlogname, argv, i, consumed);
else if (SHOULD_PARSE_ARG(SDLOG_OPTION, sdlogname, argv[i]))
PARSE_ARG(SDLOG_OPTION, sdlogname, argv, i, consumed);
logfilename = argv[i+1];
switch (*logfilename) {
#if XP_UNIX
case '|':
if (pipe(pipefds) == 0) {
pid_t pid = fork();
if (pid == 0) {
/* In child: set up stdin, parse args, and exec. */
int maxargc, nargc;
char **nargv, *token;
if (pipefds[0] != 0) {
dup2(pipefds[0], 0);
close(pipefds[0]);
}
close(pipefds[1]);
logfilename = strtok(logfilename + 1, " \t");
maxargc = 3;
nargv = (char **) malloc((maxargc+1) * sizeof(char *));
if (!nargv) exit(1);
nargc = 0;
nargv[nargc++] = logfilename;
while ((token = strtok(NULL, " \t")) != NULL) {
if (nargc == maxargc) {
maxargc *= 2;
nargv = (char**)
realloc(nargv, (maxargc+1) * sizeof(char*));
if (!nargv) exit(1);
}
nargv[nargc++] = token;
}
nargv[nargc] = NULL;
(void) setsid();
execvp(logfilename, nargv);
exit(127);
}
if (pid > 0) {
/* In parent: set logfd to the pipe's write side. */
close(pipefds[0]);
logfd = pipefds[1];
}
}
if (logfd < 0) {
fprintf(stderr,
"%s: can't pipe to trace-malloc child process %s: %s\n",
argv[0], logfilename, strerror(errno));
exit(1);
}
break;
#endif /*XP_UNIX*/
case '-':
/* Don't log from startup, but do prepare to log later. */
/* XXX traditional meaning of '-' as option argument is "stdin" or "stdout" */
if (logfilename[1] == '\0')
break;
/* FALL THROUGH */
default:
logfd = open(logfilename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (logfd < 0) {
fprintf(stderr,
"%s: can't create trace-malloc logfilename %s: %s\n",
argv[0], logfilename, strerror(errno));
exit(1);
}
break;
}
#ifndef XP_WIN32
if (consumed) {
#ifndef XP_WIN32 /* If we don't comment this out, it will crash Windows. */
int j;
/* Now remove --trace-malloc and its argument from argv. */
for (argc -= 2; i < argc; i++)
argv[i] = argv[i+2];
argc -= consumed;
for (j = i; j < argc; ++j)
argv[j] = argv[j+consumed];
argv[argc] = NULL;
#endif//if you dont comment this out it will crash windows
consumed = 0; /* don't advance next iteration */
#endif
} else {
consumed = 1;
}
}
if (tmlogname) {
int pipefds[2];
switch (*tmlogname) {
#if XP_UNIX
case '|':
if (pipe(pipefds) == 0) {
pid_t pid = fork();
if (pid == 0) {
/* In child: set up stdin, parse args, and exec. */
int maxargc, nargc;
char **nargv, *token;
if (pipefds[0] != 0) {
dup2(pipefds[0], 0);
close(pipefds[0]);
}
close(pipefds[1]);
tmlogname = strtok(tmlogname + 1, " \t");
maxargc = 3;
nargv = (char **) malloc((maxargc+1) * sizeof(char *));
if (!nargv) exit(1);
nargc = 0;
nargv[nargc++] = tmlogname;
while ((token = strtok(NULL, " \t")) != NULL) {
if (nargc == maxargc) {
maxargc *= 2;
nargv = (char**)
realloc(nargv, (maxargc+1) * sizeof(char*));
if (!nargv) exit(1);
}
nargv[nargc++] = token;
}
nargv[nargc] = NULL;
(void) setsid();
execvp(tmlogname, nargv);
exit(127);
}
if (pid > 0) {
/* In parent: set logfd to the pipe's write side. */
close(pipefds[0]);
logfd = pipefds[1];
}
}
if (logfd < 0) {
fprintf(stderr,
"%s: can't pipe to trace-malloc child process %s: %s\n",
argv[0], tmlogname, strerror(errno));
exit(1);
}
break;
#endif /*XP_UNIX*/
case '-':
/* Don't log from startup, but do prepare to log later. */
/* XXX traditional meaning of '-' as option argument is "stdin" or "stdout" */
if (tmlogname[1] == '\0')
break;
/* FALL THROUGH */
default:
logfd = open(tmlogname, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (logfd < 0) {
fprintf(stderr,
"%s: can't create trace-malloc log named %s: %s\n",
argv[0], tmlogname, strerror(errno));
exit(1);
}
break;
}
}
@ -1533,6 +1572,9 @@ PR_IMPLEMENT(void) NS_TraceMallocShutdown()
{
logfile *fp;
if (sdlogname)
NS_TraceMallocDumpAllocations(sdlogname);
if (tmstats.backtrace_failures) {
fprintf(stderr,
"TraceMalloc backtrace failures: %lu (malloc %lu dladdr %lu)\n",
@ -1683,7 +1725,7 @@ NS_TraceMallocLogTimestamp(const char *caption)
#endif
#if defined(XP_WIN32)
struct _timeb tb;
#endif
#endif
if (tmmon)

Просмотреть файл

@ -81,10 +81,6 @@ CSRCS += nsTraceMalloc.c
CPPSRCS += nsTypeInfo.cpp
EXPORTS += nsTraceMalloc.h
DEFINES += -DNS_TRACE_MALLOC
SIMPLE_PROGRAMS = bloatblame
LIBS += tmreader.o $(NSPR_LIBS)
EXTRA_DEPS = tmreader.o
endif
XPIDLSRCS = \

Просмотреть файл

Просмотреть файл

@ -56,6 +56,7 @@
#include "prlog.h"
#include "prmon.h"
#include "prprf.h"
#include "prenv.h"
#include "nsTraceMalloc.h"
#ifdef XP_WIN32
@ -68,7 +69,7 @@
#define WRITE_FLAGS "w"
#endif //WIN32
#endif /* WIN32 */
#ifdef XP_UNIX
@ -268,6 +269,7 @@ static logfile *logfile_list = NULL;
static logfile **logfile_tail = &logfile_list;
static logfile *logfp = &default_logfile;
static PRMonitor *tmmon = NULL;
static char *sdlogname = NULL; /* filename for shutdown leak log */
/* We don't want more than 32 logfiles open at once, ok? */
typedef uint32 lfd_set;
@ -318,7 +320,7 @@ retry:
static void flush_logfile(logfile *fp)
{
int len, cnt;
int fd;
int fd;
char *bp;
len = fp->pos;
@ -570,15 +572,17 @@ static callsite *calltree(int skip)
if (! ok)
return 0;
// Get the context information for this thread. That way we will
// know where our sp, fp, pc, etc. are and can fill in the
// STACKFRAME with the initial values.
/*
* Get the context information for this thread. That way we will
* know where our sp, fp, pc, etc. are and can fill in the
* STACKFRAME with the initial values.
*/
context.ContextFlags = CONTEXT_FULL;
ok = GetThreadContext(myThread, &context);
if (! ok)
return 0;
// Setup initial stack frame to walk from
/* Setup initial stack frame to walk from */
memset(&(frame[0]), 0, sizeof(frame[0]));
frame[0].AddrPC.Offset = context.Eip;
frame[0].AddrPC.Mode = AddrModeFlat;
@ -598,10 +602,11 @@ static callsite *calltree(int skip)
myThread,
&(frame[framenum]),
&context,
0, // read process memory routine
_SymFunctionTableAccess, // function table access routine
_SymGetModuleBase, // module base routine
0); // translate address routine
0, /* read process memory routine */
_SymFunctionTableAccess, /* function table access
routine */
_SymGetModuleBase, /* module base routine */
0); /* translate address routine */
if (!ok) {
break;
@ -676,7 +681,7 @@ static callsite *calltree(int skip)
{
DWORD error = GetLastError();
PR_ASSERT(error);
library = "unknown";//ew
library = "unknown";/* ew */
}
else
{
@ -707,7 +712,7 @@ static callsite *calltree(int skip)
hash = PL_HashString(library);
hep = PL_HashTableRawLookup(libraries, hash, library);
he = *hep;
library = strdup(library); //strdup it always?
library = strdup(library); /* strdup it always? */
if (he) {
library_serial = (uint32) he->value;
le = (lfdset_entry *) he;
@ -716,7 +721,7 @@ static callsite *calltree(int skip)
le = NULL;
}
} else {
// library = strdup(library);
/* library = strdup(library); */
if (library) {
library_serial = ++library_serial_generator;
he = PL_HashTableRawAdd(libraries, hep, hash, library,
@ -1430,97 +1435,131 @@ PR_IMPLEMENT(void) NS_TraceMallocStartup(int logfd)
}
/*
* Options for log files, with the log file name either as the next option
* or separated by '=' (e.g. "./mozilla --trace-malloc * malloc.log" or
* "./mozilla --trace-malloc=malloc.log").
*/
static const char TMLOG_OPTION[] = "--trace-malloc";
static const char SDLOG_OPTION[] = "--shutdown-leaks";
#define SHOULD_PARSE_ARG(name_, log_, arg_) \
(0 == strncmp(arg_, name_, sizeof(name_) - 1))
#define PARSE_ARG(name_, log_, argv_, i_, consumed_) \
PR_BEGIN_MACRO \
char _nextchar = argv_[i_][sizeof(name_) - 1]; \
if (_nextchar == '=') { \
log_ = argv_[i_] + sizeof(name_); \
consumed_ = 1; \
} else if (_nextchar == '\0') { \
log_ = argv_[i_+1]; \
consumed_ = 2; \
} \
PR_END_MACRO
PR_IMPLEMENT(int) NS_TraceMallocStartupArgs(int argc, char* argv[])
{
int i, logfd = -1;
int i, logfd = -1, consumed;
char *tmlogname = NULL; /* note global |sdlogname| */
/*
* Look for the --trace-malloc <logfile> option early, to avoid missing
* early mallocs (we miss static constructors whose output overflows the
* log file's static 16K output buffer).
*/
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "--trace-malloc") == 0 && i < argc-1) {
char *logfilename;
int pipefds[2];
for (i = 1; i < argc; i += consumed) {
consumed = 0;
if (SHOULD_PARSE_ARG(TMLOG_OPTION, tmlogname, argv[i]))
PARSE_ARG(TMLOG_OPTION, tmlogname, argv, i, consumed);
else if (SHOULD_PARSE_ARG(SDLOG_OPTION, sdlogname, argv[i]))
PARSE_ARG(SDLOG_OPTION, sdlogname, argv, i, consumed);
logfilename = argv[i+1];
switch (*logfilename) {
#if XP_UNIX
case '|':
if (pipe(pipefds) == 0) {
pid_t pid = fork();
if (pid == 0) {
/* In child: set up stdin, parse args, and exec. */
int maxargc, nargc;
char **nargv, *token;
if (pipefds[0] != 0) {
dup2(pipefds[0], 0);
close(pipefds[0]);
}
close(pipefds[1]);
logfilename = strtok(logfilename + 1, " \t");
maxargc = 3;
nargv = (char **) malloc((maxargc+1) * sizeof(char *));
if (!nargv) exit(1);
nargc = 0;
nargv[nargc++] = logfilename;
while ((token = strtok(NULL, " \t")) != NULL) {
if (nargc == maxargc) {
maxargc *= 2;
nargv = (char**)
realloc(nargv, (maxargc+1) * sizeof(char*));
if (!nargv) exit(1);
}
nargv[nargc++] = token;
}
nargv[nargc] = NULL;
(void) setsid();
execvp(logfilename, nargv);
exit(127);
}
if (pid > 0) {
/* In parent: set logfd to the pipe's write side. */
close(pipefds[0]);
logfd = pipefds[1];
}
}
if (logfd < 0) {
fprintf(stderr,
"%s: can't pipe to trace-malloc child process %s: %s\n",
argv[0], logfilename, strerror(errno));
exit(1);
}
break;
#endif /*XP_UNIX*/
case '-':
/* Don't log from startup, but do prepare to log later. */
/* XXX traditional meaning of '-' as option argument is "stdin" or "stdout" */
if (logfilename[1] == '\0')
break;
/* FALL THROUGH */
default:
logfd = open(logfilename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (logfd < 0) {
fprintf(stderr,
"%s: can't create trace-malloc logfilename %s: %s\n",
argv[0], logfilename, strerror(errno));
exit(1);
}
break;
}
#ifndef XP_WIN32
if (consumed) {
#ifndef XP_WIN32 /* If we don't comment this out, it will crash Windows. */
int j;
/* Now remove --trace-malloc and its argument from argv. */
for (argc -= 2; i < argc; i++)
argv[i] = argv[i+2];
argc -= consumed;
for (j = i; j < argc; ++j)
argv[j] = argv[j+consumed];
argv[argc] = NULL;
#endif//if you dont comment this out it will crash windows
consumed = 0; /* don't advance next iteration */
#endif
} else {
consumed = 1;
}
}
if (tmlogname) {
int pipefds[2];
switch (*tmlogname) {
#if XP_UNIX
case '|':
if (pipe(pipefds) == 0) {
pid_t pid = fork();
if (pid == 0) {
/* In child: set up stdin, parse args, and exec. */
int maxargc, nargc;
char **nargv, *token;
if (pipefds[0] != 0) {
dup2(pipefds[0], 0);
close(pipefds[0]);
}
close(pipefds[1]);
tmlogname = strtok(tmlogname + 1, " \t");
maxargc = 3;
nargv = (char **) malloc((maxargc+1) * sizeof(char *));
if (!nargv) exit(1);
nargc = 0;
nargv[nargc++] = tmlogname;
while ((token = strtok(NULL, " \t")) != NULL) {
if (nargc == maxargc) {
maxargc *= 2;
nargv = (char**)
realloc(nargv, (maxargc+1) * sizeof(char*));
if (!nargv) exit(1);
}
nargv[nargc++] = token;
}
nargv[nargc] = NULL;
(void) setsid();
execvp(tmlogname, nargv);
exit(127);
}
if (pid > 0) {
/* In parent: set logfd to the pipe's write side. */
close(pipefds[0]);
logfd = pipefds[1];
}
}
if (logfd < 0) {
fprintf(stderr,
"%s: can't pipe to trace-malloc child process %s: %s\n",
argv[0], tmlogname, strerror(errno));
exit(1);
}
break;
#endif /*XP_UNIX*/
case '-':
/* Don't log from startup, but do prepare to log later. */
/* XXX traditional meaning of '-' as option argument is "stdin" or "stdout" */
if (tmlogname[1] == '\0')
break;
/* FALL THROUGH */
default:
logfd = open(tmlogname, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (logfd < 0) {
fprintf(stderr,
"%s: can't create trace-malloc log named %s: %s\n",
argv[0], tmlogname, strerror(errno));
exit(1);
}
break;
}
}
@ -1533,6 +1572,9 @@ PR_IMPLEMENT(void) NS_TraceMallocShutdown()
{
logfile *fp;
if (sdlogname)
NS_TraceMallocDumpAllocations(sdlogname);
if (tmstats.backtrace_failures) {
fprintf(stderr,
"TraceMalloc backtrace failures: %lu (malloc %lu dladdr %lu)\n",
@ -1683,7 +1725,7 @@ NS_TraceMallocLogTimestamp(const char *caption)
#endif
#if defined(XP_WIN32)
struct _timeb tb;
#endif
#endif
if (tmmon)

Просмотреть файл

Просмотреть файл