From: jongfoster Date: Sat, 16 Mar 2002 23:54:06 +0000 (+0000) Subject: Adding graceful termination feature, to help look for memory leaks. X-Git-Tag: v_2_9_12~26 X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=commitdiff_plain;h=59e68c837eaa393a3fa0bb979b9b1da23a93e841;hp=66b279cc3553af414ba3e3d5053ab85a3cdc3f48 Adding graceful termination feature, to help look for memory leaks. If you enable this (which, by design, has to be done by hand editing config.h) and then go to http://i.j.b/die, then the program will exit cleanly after the *next* request. It should free all the memory that was used. --- diff --git a/actions.c b/actions.c index e58b6a85..9e3f24d7 100644 --- a/actions.c +++ b/actions.c @@ -1,4 +1,4 @@ -const char actions_rcs[] = "$Id: actions.c,v 1.22 2002/01/21 00:27:02 jongfoster Exp $"; +const char actions_rcs[] = "$Id: actions.c,v 1.23 2002/03/07 03:46:16 oes Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/actions.c,v $ @@ -33,6 +33,9 @@ const char actions_rcs[] = "$Id: actions.c,v 1.22 2002/01/21 00:27:02 jongfoster * * Revisions : * $Log: actions.c,v $ + * Revision 1.23 2002/03/07 03:46:16 oes + * Fixed compiler warnings + * * Revision 1.22 2002/01/21 00:27:02 jongfoster * Allowing free_action(NULL). * Moving the functions that #include actionlist.h to the end of the file, @@ -804,6 +807,33 @@ void free_current_action (struct current_action_spec *src) } +static struct file_list *current_actions_file = NULL; + + +#ifdef FEATURE_GRACEFUL_TERMINATION +/********************************************************************* + * + * Function : unload_current_actions_file + * + * Description : Unloads current actions file - reset to state at + * beginning of program. + * + * Parameters : None + * + * Returns : N/A + * + *********************************************************************/ +void unload_current_actions_file(void) +{ + if (current_actions_file) + { + current_actions_file->unloader = unload_actions_file; + current_actions_file = NULL; + } +} +#endif /* FEATURE_GRACEFUL_TERMINATION */ + + /********************************************************************* * * Function : unload_actions_file @@ -874,7 +904,6 @@ void free_alias_list(struct action_alias *alias_list) *********************************************************************/ int load_actions_file(struct client_state *csp) { - static struct file_list *current_actions_file = NULL; /* * Parser mode. diff --git a/actions.h b/actions.h index e2f99631..46758c0e 100644 --- a/actions.h +++ b/actions.h @@ -1,6 +1,6 @@ #ifndef ACTIONS_H_INCLUDED #define ACTIONS_H_INCLUDED -#define ACTIONS_H_VERSION "$Id: actions.h,v 1.5 2001/10/14 21:58:22 jongfoster Exp $" +#define ACTIONS_H_VERSION "$Id: actions.h,v 1.6 2001/10/23 21:30:30 jongfoster Exp $" /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/actions.h,v $ @@ -35,6 +35,9 @@ * * Revisions : * $Log: actions.h,v $ + * Revision 1.6 2001/10/23 21:30:30 jongfoster + * Adding error-checking to selected functions. + * * Revision 1.5 2001/10/14 21:58:22 jongfoster * Adding support for the CGI-based editor: * - Exported get_actions() @@ -112,6 +115,9 @@ extern jb_err get_action_token(char **line, char **name, char **value); extern void unload_actions_file(void *file_data); extern int load_actions_file(struct client_state *csp); +#ifdef FEATURE_GRACEFUL_TERMINATION +void unload_current_actions_file(void); +#endif /* Revision control strings from this header and associated .c file */ diff --git a/cgi.c b/cgi.c index e1960974..98d05cdc 100644 --- a/cgi.c +++ b/cgi.c @@ -1,4 +1,4 @@ -const char cgi_rcs[] = "$Id: cgi.c,v 1.48 2002/03/08 17:47:07 jongfoster Exp $"; +const char cgi_rcs[] = "$Id: cgi.c,v 1.49 2002/03/13 00:27:04 jongfoster Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/cgi.c,v $ @@ -38,6 +38,9 @@ const char cgi_rcs[] = "$Id: cgi.c,v 1.48 2002/03/08 17:47:07 jongfoster Exp $"; * * Revisions : * $Log: cgi.c,v $ + * Revision 1.49 2002/03/13 00:27:04 jongfoster + * Killing warnings + * * Revision 1.48 2002/03/08 17:47:07 jongfoster * Adding comments * @@ -330,6 +333,11 @@ static const struct cgi_dispatcher cgi_dispatchers[] = { { "", cgi_default, "Junkbuster main page" }, +#ifdef FEATURE_GRACEFUL_TERMINATION + { "die", + cgi_die, + "Shut down - Do not deploy this build in a production environment, this is a one click Denial Of Service attack!!!" }, +#endif { "show-status", cgi_show_status, "Show information about the current configuration" }, diff --git a/cgisimple.c b/cgisimple.c index 401065c2..1621baa2 100644 --- a/cgisimple.c +++ b/cgisimple.c @@ -1,4 +1,4 @@ -const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.17 2002/03/08 16:43:18 oes Exp $"; +const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.18 2002/03/12 01:44:49 oes Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/cgisimple.c,v $ @@ -36,6 +36,9 @@ const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.17 2002/03/08 16:43:18 oes Ex * * Revisions : * $Log: cgisimple.c,v $ + * Revision 1.18 2002/03/12 01:44:49 oes + * Changed default for "blocked" image from jb logo to checkboard pattern + * * Revision 1.17 2002/03/08 16:43:18 oes * Added choice beween GIF and PNG built-in images * @@ -253,6 +256,48 @@ jb_err cgi_error_404(struct client_state *csp, } +#ifdef FEATURE_GRACEFUL_TERMINATION +/********************************************************************* + * + * Function : cgi_die + * + * Description : CGI function to shut down JunkBuster. + * NOTE: Turning this on in a production build + * would be a BAD idea. An EXTREMELY BAD idea. + * In short, don't do it. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : rsp = http_response data structure for output + * 3 : parameters = map of cgi parameters + * + * CGI Parameters : none + * + * Returns : JB_ERR_OK on success + * JB_ERR_MEMORY on out-of-memory error. + * + *********************************************************************/ +jb_err cgi_die (struct client_state *csp, + struct http_response *rsp, + const struct map *parameters) +{ + assert(csp); + assert(rsp); + assert(parameters); + + /* quit */ + g_terminate = 1; + + /* + * I don't really care what gets sent back to the browser. + * Take the easy option - "out of memory" page. + */ + + return JB_ERR_MEMORY; +} +#endif /* def FEATURE_GRACEFUL_TERMINATION */ + + /********************************************************************* * * Function : cgi_show_request diff --git a/cgisimple.h b/cgisimple.h index afa06cab..adb14f16 100644 --- a/cgisimple.h +++ b/cgisimple.h @@ -1,6 +1,6 @@ #ifndef CGISIMPLE_H_INCLUDED #define CGISIMPLE_H_INCLUDED -#define CGISIMPLE_H_VERSION "$Id: cgisimple.h,v 1.6 2002/03/07 03:48:59 oes Exp $" +#define CGISIMPLE_H_VERSION "$Id: cgisimple.h,v 1.7 2002/03/08 16:43:59 oes Exp $" /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/cgisimple.h,v $ @@ -38,6 +38,9 @@ * * Revisions : * $Log: cgisimple.h,v $ + * Revision 1.7 2002/03/08 16:43:59 oes + * Renamed cgi_transparent_png to cgi_transparent_image + * * Revision 1.6 2002/03/07 03:48:59 oes * - Changed built-in images from GIF to PNG * (with regard to Unisys patent issue) @@ -107,6 +110,12 @@ extern jb_err cgi_transparent_image (struct client_state *csp, struct http_response *rsp, const struct map *parameters); +#ifdef FEATURE_GRACEFUL_TERMINATION +extern jb_err cgi_die (struct client_state *csp, + struct http_response *rsp, + const struct map *parameters); +#endif + /* Revision control strings from this header and associated .c file */ extern const char cgisimple_rcs[]; extern const char cgisimple_h_rcs[]; diff --git a/jcc.c b/jcc.c index bdb26a32..4e28e4f1 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.81 2002/03/12 01:42:50 oes Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.82 2002/03/13 00:27:05 jongfoster Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -33,6 +33,9 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.81 2002/03/12 01:42:50 oes Exp $"; * * Revisions : * $Log: jcc.c,v $ + * Revision 1.82 2002/03/13 00:27:05 jongfoster + * Killing warnings + * * Revision 1.81 2002/03/12 01:42:50 oes * Introduced modular filters * @@ -583,6 +586,9 @@ int urls_read = 0; /* total nr of urls read inc rejected */ int urls_rejected = 0; /* total nr of urls rejected */ #endif /* def FEATURE_STATISTICS */ +#ifdef FEATURE_GRACEFUL_TERMINATION +int g_terminate = 0; +#endif static void listen_loop(void); static void chat(struct client_state *csp); @@ -1974,7 +1980,11 @@ static void listen_loop(void) bfd = bind_port_helper(config); +#ifdef FEATURE_GRACEFUL_TERMINATION + while (!g_terminate) +#else for (;;) +#endif { #if !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) while (waitpid(-1, NULL, WNOHANG) > 0) @@ -2202,7 +2212,45 @@ static void listen_loop(void) serve(csp); } } - /* NOTREACHED */ + + /* NOTREACHED unless FEATURE_GRACEFUL_TERMINATION is defined */ + + /* Clean up. Aim: free all memory (no leaks) */ +#ifdef FEATURE_GRACEFUL_TERMINATION + + log_error(LOG_LEVEL_ERROR, "Graceful termination requested"); + + unload_current_config_file(); + unload_current_actions_file(); + unload_current_re_filterfile(); +#ifdef FEATURE_TRUST + unload_current_trust_file(); +#endif + + if (config->multi_threaded) + { + int i = 60; + do + { + sleep(1); + sweep(); + } while ((clients->next != NULL) && (--i > 0)); + + if (i <= 0) + { + log_error(LOG_LEVEL_ERROR, "Graceful termination failed - still some live clients after 1 minute wait."); + } + } + sweep(); + sweep(); + +#if defined(_WIN32) && !defined(_WIN_CONSOLE) + /* Cleanup - remove taskbar icon etc. */ + TermLogWindow(); +#endif + + exit(0); +#endif /* FEATURE_GRACEFUL_TERMINATION */ } diff --git a/jcc.h b/jcc.h index c233a1a0..15784400 100644 --- a/jcc.h +++ b/jcc.h @@ -1,6 +1,6 @@ #ifndef JCC_H_INCLUDED #define JCC_H_INCLUDED -#define JCC_H_VERSION "$Id: jcc.h,v 1.8 2002/03/04 18:19:49 oes Exp $" +#define JCC_H_VERSION "$Id: jcc.h,v 1.9 2002/03/07 03:52:44 oes Exp $" /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.h,v $ @@ -35,6 +35,9 @@ * * Revisions : * $Log: jcc.h,v $ + * Revision 1.9 2002/03/07 03:52:44 oes + * Set logging to tty for --no-daemon mode + * * Revision 1.8 2002/03/04 18:19:49 oes * Added extern const char *pidfile * @@ -98,6 +101,10 @@ extern const char *pidfile; #endif extern int no_daemon; +#ifdef FEATURE_GRACEFUL_TERMINATION +extern int g_terminate; +#endif + /* Functions */ #ifdef __MINGW32__ diff --git a/loadcfg.c b/loadcfg.c index 98814659..77b12d39 100644 --- a/loadcfg.c +++ b/loadcfg.c @@ -1,4 +1,4 @@ -const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.35 2002/03/07 03:52:44 oes Exp $"; +const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.36 2002/03/13 00:27:05 jongfoster Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/loadcfg.c,v $ @@ -35,6 +35,9 @@ const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.35 2002/03/07 03:52:44 oes Exp $" * * Revisions : * $Log: loadcfg.c,v $ + * Revision 1.36 2002/03/13 00:27:05 jongfoster + * Killing warnings + * * Revision 1.35 2002/03/07 03:52:44 oes * Set logging to tty for --no-daemon mode * @@ -455,6 +458,30 @@ void unload_configfile (void * data) } +#ifdef FEATURE_GRACEFUL_TERMINATION +/********************************************************************* + * + * Function : unload_current_config_file + * + * Description : Unloads current config file - reset to state at + * beginning of program. + * + * Parameters : None + * + * Returns : N/A + * + *********************************************************************/ +void unload_current_config_file(void) +{ + if (current_configfile) + { + current_configfile->unloader = unload_configfile; + current_configfile = NULL; + } +} +#endif + + /********************************************************************* * * Function : load_config diff --git a/loadcfg.h b/loadcfg.h index 5c7e2f00..85c3ab66 100644 --- a/loadcfg.h +++ b/loadcfg.h @@ -1,6 +1,6 @@ #ifndef LOADCFG_H_INCLUDED #define LOADCFG_H_INCLUDED -#define LOADCFG_H_VERSION "$Id: loadcfg.h,v 1.7 2001/07/30 22:08:36 jongfoster Exp $" +#define LOADCFG_H_VERSION "$Id: loadcfg.h,v 1.8 2001/12/30 14:07:32 steudten Exp $" /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/loadcfg.h,v $ @@ -37,6 +37,14 @@ * * Revisions : * $Log: loadcfg.h,v $ + * Revision 1.8 2001/12/30 14:07:32 steudten + * - Add signal handling (unix) + * - Add SIGHUP handler (unix) + * - Add creation of pidfile (unix) + * - Add action 'top' in rc file (RH) + * - Add entry 'SIGNALS' to manpage + * - Add exit message to logfile (unix) + * * Revision 1.7 2001/07/30 22:08:36 jongfoster * Tidying up #defines: * - All feature #defines are now of the form FEATURE_xxx @@ -150,6 +158,9 @@ extern short int MustReload; extern struct configuration_spec * load_config(void); +#ifdef FEATURE_GRACEFUL_TERMINATION +void unload_current_config_file(void); +#endif /* Revision control strings from this header and associated .c file */ extern const char loadcfg_rcs[]; diff --git a/loaders.c b/loaders.c index 5a81363c..a2dd8047 100644 --- a/loaders.c +++ b/loaders.c @@ -1,4 +1,4 @@ -const char loaders_rcs[] = "$Id: loaders.c,v 1.43 2002/03/16 20:28:34 oes Exp $"; +const char loaders_rcs[] = "$Id: loaders.c,v 1.44 2002/03/16 21:51:00 jongfoster Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/loaders.c,v $ @@ -35,6 +35,9 @@ const char loaders_rcs[] = "$Id: loaders.c,v 1.43 2002/03/16 20:28:34 oes Exp $" * * Revisions : * $Log: loaders.c,v $ + * Revision 1.44 2002/03/16 21:51:00 jongfoster + * Fixing free(NULL). + * * Revision 1.43 2002/03/16 20:28:34 oes * Added descriptions to the filters so users will know what they select in the cgi editor * @@ -948,18 +951,46 @@ char *read_config_line(char *buf, size_t buflen, FILE *fp, unsigned long *linenu *********************************************************************/ static void unload_trustfile(void *f) { - struct block_spec *b = (struct block_spec *)f; - if (b == NULL) return; + struct block_spec *cur = (struct block_spec *)f; + struct block_spec *next; - unload_trustfile(b->next); /* Stack is cheap, isn't it? */ + while (cur != NULL) + { + next = cur->next; - free_url_spec(b->url); + free_url_spec(cur->url); + free(cur); - freez(b); + cur = next; + } } +#ifdef FEATURE_GRACEFUL_TERMINATION +/********************************************************************* + * + * Function : unload_current_trust_file + * + * Description : Unloads current trust file - reset to state at + * beginning of program. + * + * Parameters : None + * + * Returns : N/A + * + *********************************************************************/ +void unload_current_trust_file(void) +{ + if (current_trustfile) + { + current_trustfile->unloader = unload_trustfile; + current_trustfile = NULL; + } +} +#endif /* FEATURE_GRACEFUL_TERMINATION */ + + /********************************************************************* * * Function : load_trustfile @@ -1133,6 +1164,30 @@ static void unload_re_filterfile(void *f) } +#ifdef FEATURE_GRACEFUL_TERMINATION +/********************************************************************* + * + * Function : unload_current_re_filterfile + * + * Description : Unloads current re_filter file - reset to state at + * beginning of program. + * + * Parameters : None + * + * Returns : N/A + * + *********************************************************************/ +void unload_current_re_filterfile(void) +{ + if (current_re_filterfile) + { + current_re_filterfile->unloader = unload_re_filterfile; + current_re_filterfile = NULL; + } +} +#endif + + /********************************************************************* * * Function : load_re_filterfile diff --git a/loaders.h b/loaders.h index 0637f7c6..8b6e29b0 100644 --- a/loaders.h +++ b/loaders.h @@ -1,6 +1,6 @@ #ifndef LOADERS_H_INCLUDED #define LOADERS_H_INCLUDED -#define LOADERS_H_VERSION "$Id: loaders.h,v 1.15 2002/01/22 23:46:18 jongfoster Exp $" +#define LOADERS_H_VERSION "$Id: loaders.h,v 1.16 2002/03/07 03:46:17 oes Exp $" /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/loaders.h,v $ @@ -37,6 +37,9 @@ * * Revisions : * $Log: loaders.h,v $ + * Revision 1.16 2002/03/07 03:46:17 oes + * Fixed compiler warnings + * * Revision 1.15 2002/01/22 23:46:18 jongfoster * Moving edit_read_line() and simple_read_line() to loaders.c, and * extending them to support reading MS-DOS, Mac and UNIX style files @@ -193,6 +196,12 @@ extern int load_re_filterfile(struct client_state *csp); extern int load_trustfile(struct client_state *csp); #endif /* def FEATURE_TRUST */ +#ifdef FEATURE_GRACEFUL_TERMINATION +#ifdef FEATURE_TRUST +void unload_current_trust_file(void); +#endif +void unload_current_re_filterfile(void); +#endif /* FEATURE_GRACEFUL_TERMINATION */ extern void add_loader(int (*loader)(struct client_state *),