From 2d54b109f67af610357159607ab41f6919ce1b94 Mon Sep 17 00:00:00 2001 From: patacongo Date: Fri, 11 Sep 2009 15:15:35 +0000 Subject: Add memory debug support to THTTPD git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2033 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/netutils/thttpd/Make.defs | 2 +- nuttx/netutils/thttpd/cgi-src/ssi.c | 3 +- nuttx/netutils/thttpd/config.h | 6 ++ nuttx/netutils/thttpd/fdwatch.c | 15 +-- nuttx/netutils/thttpd/httpd_alloc.c | 188 ++++++++++++++++++++++++++++++++++++ nuttx/netutils/thttpd/httpd_alloc.h | 82 ++++++++++++++++ nuttx/netutils/thttpd/libhttpd.c | 89 +++++------------ nuttx/netutils/thttpd/libhttpd.h | 15 --- nuttx/netutils/thttpd/thttpd.c | 7 +- nuttx/netutils/thttpd/timers.c | 5 +- 10 files changed, 317 insertions(+), 95 deletions(-) create mode 100755 nuttx/netutils/thttpd/httpd_alloc.c create mode 100755 nuttx/netutils/thttpd/httpd_alloc.h (limited to 'nuttx/netutils') diff --git a/nuttx/netutils/thttpd/Make.defs b/nuttx/netutils/thttpd/Make.defs index a80d36abf..532ab4719 100644 --- a/nuttx/netutils/thttpd/Make.defs +++ b/nuttx/netutils/thttpd/Make.defs @@ -34,5 +34,5 @@ ############################################################################ THTTPD_ASRCS = -THTTPD_CSRCS = thttpd.c libhttpd.c timers.c fdwatch.c tdate_parse.c +THTTPD_CSRCS = thttpd.c libhttpd.c httpd_alloc.c timers.c fdwatch.c tdate_parse.c diff --git a/nuttx/netutils/thttpd/cgi-src/ssi.c b/nuttx/netutils/thttpd/cgi-src/ssi.c index a4b81d45a..4afb141f9 100644 --- a/nuttx/netutils/thttpd/cgi-src/ssi.c +++ b/nuttx/netutils/thttpd/cgi-src/ssi.c @@ -499,7 +499,6 @@ static void do_echo(FILE *instream, char *vfilename, char *filename, char *directive, char *tag, char *val) { char *cp; - time_t t; /* Prints the value of one of the include variables. Any dates are * printed subject to the currently configured g_timeformat. The only valid @@ -550,7 +549,7 @@ static void do_echo(FILE *instream, char *vfilename, char *filename, /* Same as DATE_LOCAL but in Greenwich mean time. */ gettimeofday(&tm, NULL); - show_time(t, 1); + show_time(tm.tv_sec, 1); } else if (strcmp(val, "LAST_MODIFIED") == 0) { diff --git a/nuttx/netutils/thttpd/config.h b/nuttx/netutils/thttpd/config.h index dce61a32d..5eade0d47 100644 --- a/nuttx/netutils/thttpd/config.h +++ b/nuttx/netutils/thttpd/config.h @@ -200,6 +200,12 @@ # define CONFIG_THTTPD_IDLE_SEND_LIMIT_SEC 300 # endif +/* Memory debug instrumentation depends on other debug options */ + +#if (!defined(CONFIG_DEBUG) || !defined(CONFIG_DEBUG_NET)) && defined(CONFIG_THTTPD_MEMDEBUG) +# undef CONFIG_THTTPD_MEMDEBUG +#endif + /* Tilde mapping. Many URLs use ~username to indicate a user's home directory. thttpd * provides two options for mapping this construct to an actual filename. * diff --git a/nuttx/netutils/thttpd/fdwatch.c b/nuttx/netutils/thttpd/fdwatch.c index 9f2003bc5..2346d7450 100644 --- a/nuttx/netutils/thttpd/fdwatch.c +++ b/nuttx/netutils/thttpd/fdwatch.c @@ -47,6 +47,7 @@ #include #include "config.h" +#include "httpd_alloc.h" #include "fdwatch.h" #ifdef CONFIG_THTTPD @@ -140,19 +141,19 @@ struct fdwatch_s *fdwatch_initialize(int nfds) fw->nfds = nfds; - fw->client = (void**)malloc(sizeof(void*) * nfds); + fw->client = (void**)httpd_malloc(sizeof(void*) * nfds); if (!fw->client) { goto errout_with_allocations; } - fw->pollfds = (struct pollfd*)malloc(sizeof(struct pollfd) * nfds); + fw->pollfds = (struct pollfd*)httpd_malloc(sizeof(struct pollfd) * nfds); if (!fw->pollfds) { goto errout_with_allocations; } - fw->ready = (uint8*)malloc(sizeof(uint8) * nfds); + fw->ready = (uint8*)httpd_malloc(sizeof(uint8) * nfds); if (!fw->ready) { goto errout_with_allocations; @@ -175,20 +176,20 @@ void fdwatch_uninitialize(struct fdwatch_s *fw) fdwatch_dump("Uninitializing:", fw); if (fw->client) { - free(fw->client); + httpd_free(fw->client); } if (fw->pollfds) { - free(fw->pollfds); + httpd_free(fw->pollfds); } if (fw->ready) { - free(fw->ready); + httpd_free(fw->ready); } - free(fw); + httpd_free(fw); } } diff --git a/nuttx/netutils/thttpd/httpd_alloc.c b/nuttx/netutils/thttpd/httpd_alloc.c new file mode 100755 index 000000000..009dc6541 --- /dev/null +++ b/nuttx/netutils/thttpd/httpd_alloc.c @@ -0,0 +1,188 @@ +/**************************************************************************** + * netutils/thttpd/httpd_alloc.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "config.h" +#include "httpd_alloc.h" + +#ifdef CONFIG_THTTPD + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET) +static int g_nallocations = 0; +static size_t g_allocated = 0; +#endif + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET) +FAR void *httpd_malloc(size_t nbytes) +{ + void *ptr = malloc(nbytes); + if (!ptr) + { + ndbg("Allocation of %d bytes failed\n", nbytes); + } + else + { +#ifdef CONFIG_THTTPD_MEMDEBUG + nvdbg("Allocated %d bytes at %p\n", nbytes, ptr); +#endif + g_nallocations++; + g_allocated += nbytes; + } +#ifdef CONFIG_THTTPD_MEMDEBUG + httpd_memstats(); +#endif + return ptr; +} +#endif + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET) +FAR void *httpd_realloc(FAR void *oldptr, size_t oldsize, size_t newsize) +{ + void *ptr = realloc(oldptr, newsize); + if (!ptr) + { + ndbg("Re-allocation from %d to %d bytes failed\n", + oldsize, newsize); + } + else + { +#ifdef CONFIG_THTTPD_MEMDEBUG + nvdbg("Re-allocated form %d to %d bytes (from %p to %p)\n", + oldsize, newsize, oldptr, ptr); +#endif + g_allocated += (newsize - oldsize); + } +#ifdef CONFIG_THTTPD_MEMDEBUG + httpd_memstats(); +#endif + return ptr; +} +#endif + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET) +void httpd_free(FAR void *ptr) +{ + free(ptr); +#ifdef CONFIG_THTTPD_MEMDEBUG + nvdbg("Freed memory at %p\n", ptr); + httpd_memstats(); +#endif +} +#endif + +/* Helpers to implement dynamically allocated strings */ + +void httpd_realloc_str(char **pstr, size_t *maxsize, size_t size) +{ + size_t oldsize; + if (*maxsize == 0) + { + *maxsize = MAX(CONFIG_THTTPD_IOBUFFERSIZE, size + CONFIG_THTTPD_REALLOCINCR); + *pstr = NEW(char, *maxsize + 1); + } + else if (size > *maxsize) + { + oldsize = *maxsize; + *maxsize = MAX(oldsize * 2, size * 5 / 4); + *pstr = httpd_realloc(*pstr, oldsize + 1, *maxsize + 1); + } + else + { + return; + } + + if (!*pstr) + { + ndbg("out of memory reallocating a string to %d bytes\n", *maxsize); + exit(1); + } +} + +/* Generate debugging statistics */ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET) +void httpd_memstats(void) +{ +#ifdef CONFIG_THTTPD_MEMDEBUG + static struct mallinfo mm; +#endif + + ndbg("%d allocations (%lu bytes)\n", g_nallocations, (unsigned long)g_allocated); + + /* Get the current memory usage */ + +#ifdef CONFIG_THTTPD_MEMDEBUG +#ifdef CONFIG_CAN_PASS_STRUCTS + mm = mallinfo(); +#else + (void)mallinfo(&mm); +#endif + ndbg("arena: %08x ordblks: %08x mxordblk: %08x uordblks: %08x fordblks: %08x\n", + mm.arena, mm.ordblks, mm.mxordblk, mm.uordblks, mm.fordblks); +#endif +} +#endif + +#endif /* CONFIG_THTTPD */ diff --git a/nuttx/netutils/thttpd/httpd_alloc.h b/nuttx/netutils/thttpd/httpd_alloc.h new file mode 100755 index 000000000..dd687a583 --- /dev/null +++ b/nuttx/netutils/thttpd/httpd_alloc.h @@ -0,0 +1,82 @@ +/**************************************************************************** + * netutils/thttpd/httpd_alloc.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __NETUTILS_THTTPD_HTTDP_ALLOC_H +#define __NETUTILS_THTTPD_HTTDP_ALLOC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "config.h" + +#ifdef CONFIG_THTTPD + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/* Allows all memory management calls to be intercepted */ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET) +extern FAR void *httpd_malloc(size_t nbytes); +extern FAR void *httpd_realloc(FAR void *oldptr, size_t oldsize, size_t newsize); +extern void httpd_free(FAR void *ptr); +#else +# define httpd_malloc(n) malloc(n) +# define httpd_realloc(p,o,n) realloc(p,n) +# define httpd_free(p) free(p) +#endif + +/* Helpers to support allocations in multiples of a type size */ + +#define NEW(t,n) ((t*)httpd_malloc(sizeof(t)*(n))) +#define RENEW(p,t,o,n) ((t*)httpd_realloc((void*)p, sizeof(t)*(o), sizeof(t)*(n))) + +/* Helpers to implement dynamically allocated strings */ + +extern void httpd_realloc_str(char **pstr, size_t *maxsizeP, size_t size); + +/* Generate debugging statistics */ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET) +extern void httpd_memstats(void); +#else +# define httpd_memstats() +#endif + +#endif /* CONFIG_THTTPD */ +#endif /* __NETUTILS_THTTPD_HTTDP_ALLOC_H */ diff --git a/nuttx/netutils/thttpd/libhttpd.c b/nuttx/netutils/thttpd/libhttpd.c index 55e56115f..71f8b8223 100644 --- a/nuttx/netutils/thttpd/libhttpd.c +++ b/nuttx/netutils/thttpd/libhttpd.c @@ -63,6 +63,7 @@ #include "config.h" #include "libhttpd.h" +#include "httpd_alloc.h" #include "timers.h" #include "tdate_parse.h" #include "fdwatch.h" @@ -222,8 +223,6 @@ static size_t sockaddr_len(httpd_sockaddr *saP); */ static pid_t main_thread; -static int str_alloc_count = 0; -static size_t str_alloc_size = 0; /* This is the 'root' of the Filesystem as seen by the HTTP client */ @@ -295,10 +294,10 @@ static void free_httpd_server(httpd_server * hs) { if (hs->hostname) { - free(hs->hostname); + httpd_free(hs->hostname); } - free(hs); + httpd_free(hs); } } @@ -1791,13 +1790,14 @@ static void ls_child(int argc, char **argv) { maxnames = 100; names = NEW(char, maxnames * (MAXPATHLEN + 1)); - nameptrs = NEW(char *, maxnames); + nameptrs = NEW(char*, maxnames); } else { + oldmax = maxnames; maxnames *= 2; - names = RENEW(names, char, maxnames * (MAXPATHLEN + 1)); - nameptrs = RENEW(nameptrs, char *, maxnames); + names = RENEW(names, char, oldmax*(MAXPATHLEN+1), maxnames*(MAXPATHLEN + 1)); + nameptrs = RENEW(nameptrs, char*, oldmax, maxnames); } if (!names || !nameptrs) @@ -2756,7 +2756,7 @@ static int cgi_child(int argc, char **argv) goto errout_with_descriptors; } - buffer = (char*)malloc(CONFIG_THTTPD_IOBUFFERSIZE); + buffer = (char*)httpd_malloc(CONFIG_THTTPD_IOBUFFERSIZE); if (!buffer) { ndbg("buffer allocation failed\n"); @@ -2837,9 +2837,9 @@ errout_with_watch: /* Free memory */ errout_with_buffer: - free(buffer); + httpd_free(buffer); errout_with_header: - free(hdr.buffer); + httpd_free(hdr.buffer); /* Close all descriptors */ @@ -3222,34 +3222,6 @@ void httpd_clear_ndelay(int fd) } } -void httpd_realloc_str(char **strP, size_t * maxsizeP, size_t size) -{ - if (*maxsizeP == 0) - { - *maxsizeP = MAX(CONFIG_THTTPD_IOBUFFERSIZE, size + CONFIG_THTTPD_REALLOCINCR); - *strP = NEW(char, *maxsizeP + 1); - ++str_alloc_count; - str_alloc_size += *maxsizeP; - } - else if (size > *maxsizeP) - { - str_alloc_size -= *maxsizeP; - *maxsizeP = MAX(*maxsizeP * 2, size * 5 / 4); - *strP = RENEW(*strP, char, *maxsizeP + 1); - str_alloc_size += *maxsizeP; - } - else - { - return; - } - - if (!*strP) - { - ndbg("out of memory reallocating a string to %d bytes\n", *maxsizeP); - exit(1); - } -} - void httpd_send_err(httpd_conn *hc, int status, const char *title, const char *extraheads, const char *form, const char *arg) { @@ -4145,21 +4117,21 @@ void httpd_destroy_conn(httpd_conn *hc) { if (hc->initialized) { - free((void *)hc->read_buf); - free((void *)hc->decodedurl); - free((void *)hc->origfilename); - free((void *)hc->expnfilename); - free((void *)hc->encodings); - free((void *)hc->pathinfo); - free((void *)hc->query); - free((void *)hc->accept); - free((void *)hc->accepte); - free((void *)hc->reqhost); - free((void *)hc->hostdir); - free((void *)hc->remoteuser); - free((void *)hc->buffer); + httpd_free((void *)hc->read_buf); + httpd_free((void *)hc->decodedurl); + httpd_free((void *)hc->origfilename); + httpd_free((void *)hc->expnfilename); + httpd_free((void *)hc->encodings); + httpd_free((void *)hc->pathinfo); + httpd_free((void *)hc->query); + httpd_free((void *)hc->accept); + httpd_free((void *)hc->accepte); + httpd_free((void *)hc->reqhost); + httpd_free((void *)hc->hostdir); + httpd_free((void *)hc->remoteuser); + httpd_free((void *)hc->buffer); #ifdef CONFIG_THTTPD_TILDE_MAP2 - free((void *)hc->altdir); + httpd_free((void *)hc->altdir); #endif /*CONFIG_THTTPD_TILDE_MAP2 */ hc->initialized = 0; } @@ -4560,18 +4532,5 @@ int httpd_write(int fd, const void *buf, size_t nbytes) return ntotal; } -/* Generate debugging statistics */ - -#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET) -void httpd_logstats(long secs) -{ - if (str_alloc_count > 0) - { - ndbg(" libhttpd - %d strings allocated, %lu bytes (%g bytes/str)\n", - str_alloc_count, (unsigned long)str_alloc_size, - (float)str_alloc_size / str_alloc_count); - } -} -#endif #endif /* CONFIG_THTTPD */ diff --git a/nuttx/netutils/thttpd/libhttpd.h b/nuttx/netutils/thttpd/libhttpd.h index a2f2e25f2..2a2afdaf0 100644 --- a/nuttx/netutils/thttpd/libhttpd.h +++ b/nuttx/netutils/thttpd/libhttpd.h @@ -65,9 +65,6 @@ # define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif -#define NEW(t,n) ((t*) malloc( sizeof(t) * (n) )) -#define RENEW(o,t,n) ((t*) realloc( (void*) o, sizeof(t) * (n) )) - /* Enable special instrumentation to track down "400 Bad Request" problems */ #undef CONFIG_THTTPD_BADREQUEST /* Define to enable "Bad Request" instrumentation */ @@ -327,10 +324,6 @@ extern const char httpd_err408form[]; extern const char *httpd_method_str(int method); -/* Reallocate a string. */ - -extern void httpd_realloc_str(char **strP, size_t *maxsizeP, size_t size); - /* Format a network socket to a string representation. */ extern char *httpd_ntoa(httpd_sockaddr * saP); @@ -343,14 +336,6 @@ extern void httpd_set_ndelay(int fd); extern void httpd_clear_ndelay(int fd); -/* Generate debugging statistics syslog message. */ - -#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET) -extern void httpd_logstats(long secs); -#else -# define httpd_logstats(secs) -#endif - /* Read to requested buffer, accounting for interruptions and EOF */ extern int httpd_read(int fd, const void *buf, size_t nbytes); diff --git a/nuttx/netutils/thttpd/thttpd.c b/nuttx/netutils/thttpd/thttpd.c index 26a08b60b..224ccd1af 100644 --- a/nuttx/netutils/thttpd/thttpd.c +++ b/nuttx/netutils/thttpd/thttpd.c @@ -59,6 +59,7 @@ #include "config.h" #include "fdwatch.h" #include "libhttpd.h" +#include "httpd_alloc.h" #include "timers.h" #ifdef CONFIG_THTTPD @@ -163,7 +164,7 @@ static void shut_down(void) if (connects[cnum].hc != NULL) { httpd_destroy_conn(connects[cnum].hc); - free((void *)connects[cnum].hc); + httpd_free((void *)connects[cnum].hc); connects[cnum].hc = NULL; } } @@ -180,7 +181,7 @@ static void shut_down(void) } tmr_destroy(); - free((void *)connects); + httpd_free((void *)connects); } static int handle_newconnect(struct timeval *tv, int listen_fd) @@ -681,7 +682,7 @@ static void logstats(struct timeval *nowP) ndbg("up %ld seconds, stats for %ld seconds\n", up_secs, stats_secs); thttpd_logstats(stats_secs); - httpd_logstats(stats_secs); + httpd_memstats(); fdwatch_logstats(fw, stats_secs); tmr_logstats(stats_secs); } diff --git a/nuttx/netutils/thttpd/timers.c b/nuttx/netutils/thttpd/timers.c index b005da20b..e67adb37a 100644 --- a/nuttx/netutils/thttpd/timers.c +++ b/nuttx/netutils/thttpd/timers.c @@ -45,6 +45,7 @@ #include #include +#include "httpd_alloc.h" #include "timers.h" /**************************************************************************** @@ -202,7 +203,7 @@ Timer *tmr_create(struct timeval *nowP, TimerProc * timer_proc, } else { - t = (Timer*)malloc(sizeof(Timer)); + t = (Timer*)httpd_malloc(sizeof(Timer)); if (!t) { return NULL; @@ -352,7 +353,7 @@ void tmr_cleanup(void) t = free_timers; free_timers = t->next; free_count--; - free((void*)t); + httpd_free((void*)t); alloc_count--; } } -- cgit v1.2.3