2 * Copyright (c) 2008, 2009, 2010 Nicira Networks.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "leak-checker.h"
20 #include "backtrace.h"
23 VLOG_DEFINE_THIS_MODULE(leak_checker)
25 #ifndef HAVE_MALLOC_HOOKS
27 leak_checker_start(const char *file_name OVS_UNUSED)
29 VLOG_WARN("not enabling leak checker because the libc in use does not "
30 "have the required hooks");
34 leak_checker_set_limit(off_t max_size OVS_UNUSED)
39 leak_checker_claim(const void *p OVS_UNUSED)
44 leak_checker_usage(void)
46 printf(" --check-leaks=FILE (accepted but ignored in this build)\n");
48 #else /* HAVE_MALLOC_HOOKS */
54 typedef void *malloc_hook_type(size_t, const void *);
55 typedef void *realloc_hook_type(void *, size_t, const void *);
56 typedef void free_hook_type(void *, const void *);
59 malloc_hook_type *malloc_hook_func;
60 realloc_hook_type *realloc_hook_func;
61 free_hook_type *free_hook_func;
64 static malloc_hook_type hook_malloc;
65 static realloc_hook_type hook_realloc;
66 static free_hook_type hook_free;
68 static struct hooks libc_hooks;
69 static const struct hooks our_hooks = { hook_malloc, hook_realloc, hook_free };
72 static off_t limit = 10 * 1000 * 1000;
75 get_hooks(struct hooks *hooks)
77 hooks->malloc_hook_func = __malloc_hook;
78 hooks->realloc_hook_func = __realloc_hook;
79 hooks->free_hook_func = __free_hook;
83 set_hooks(const struct hooks *hooks)
85 __malloc_hook = hooks->malloc_hook_func;
86 __realloc_hook = hooks->realloc_hook_func;
87 __free_hook = hooks->free_hook_func;
91 leak_checker_start(const char *file_name)
94 file = fopen(file_name, "w");
96 VLOG_WARN("failed to create \"%s\": %s",
97 file_name, strerror(errno));
100 setvbuf(file, NULL, _IOLBF, 0);
101 VLOG_WARN("enabled memory leak logging to \"%s\"", file_name);
102 get_hooks(&libc_hooks);
103 set_hooks(&our_hooks);
108 leak_checker_stop(void)
113 set_hooks(&libc_hooks);
114 VLOG_WARN("disabled memory leak logging");
119 leak_checker_set_limit(off_t limit_)
125 leak_checker_usage(void)
127 printf(" --check-leaks=FILE log malloc and free calls to FILE\n");
130 static void PRINTF_FORMAT(1, 2)
131 log_callers(const char *format, ...)
133 struct backtrace backtrace;
137 va_start(args, format);
138 vfprintf(file, format, args);
142 backtrace_capture(&backtrace);
143 for (i = 0; i < backtrace.n_frames; i++) {
144 fprintf(file, " 0x%"PRIxPTR, backtrace.frames[i]);
156 VLOG_WARN("error writing leak checker log file");
161 if (count++ >= 100 && limit) {
164 if (fstat(fileno(file), &s) < 0) {
165 VLOG_WARN("cannot fstat leak checker log file: %s",
170 if (s.st_size > limit) {
171 VLOG_WARN("leak checker log file size exceeded limit");
178 set_hooks(&our_hooks);
183 hook_malloc(size_t size, const void *caller OVS_UNUSED)
187 set_hooks(&libc_hooks);
189 get_hooks(&libc_hooks);
191 log_callers("malloc(%zu) -> %p", size, p);
198 leak_checker_claim(const void *p)
205 set_hooks(&libc_hooks);
206 log_callers("claim(%p)", p);
212 hook_free(void *p, const void *caller OVS_UNUSED)
218 set_hooks(&libc_hooks);
220 get_hooks(&libc_hooks);
222 log_callers("free(%p)", p);
228 hook_realloc(void *p, size_t size, const void *caller OVS_UNUSED)
232 set_hooks(&libc_hooks);
233 q = realloc(p, size);
234 get_hooks(&libc_hooks);
237 log_callers("realloc(%p, %zu) -> %p", p, size, q);
244 #endif /* HAVE_MALLOC_HOOKS */