From: james Date: Thu, 23 Nov 2006 22:05:14 +0000 (+0000) Subject: Fixed issue where struct env_set methods that X-Git-Tag: v2.1_rc2~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2a64816b391395d925e0f7ff79d200bbb562fe7e;p=thirdparty%2Fopenvpn.git Fixed issue where struct env_set methods that change the value of an existing name=value pair would delay the freeing of the memory held by the previous name=value pair until the underlying client instance object is closed. This could cause a server that handles long-term client connections, resulting in many periodic calls to verify_callback, to needlessly grow the env_set memory allocation until the underlying client instance object is closed. git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@1493 e7ae566f-a301-0410-adde-c780ea21d3b5 --- diff --git a/init.c b/init.c index 244f03cfa..2cff87c2c 100644 --- a/init.c +++ b/init.c @@ -2272,10 +2272,22 @@ do_close_ifconfig_pool_persist (struct context *c) static void do_inherit_env (struct context *c, const struct env_set *src) { - c->c2.es = env_set_create (&c->c2.gc); + c->c2.es = env_set_create (NULL); + c->c2.es_owned = true; env_set_inherit (c->c2.es, src); } +static void +do_env_set_destroy (struct context *c) +{ + if (c->c2.es && c->c2.es_owned) + { + env_set_destroy (c->c2.es); + c->c2.es = NULL; + c->c2.es_owned = false; + } +} + /* * Fast I/O setup. Fast I/O is an optimization which only works * if all of the following are true: @@ -2798,6 +2810,9 @@ close_instance (struct context *c) /* close --ifconfig-pool-persist obj */ do_close_ifconfig_pool_persist (c); + /* free up environmental variable store */ + do_env_set_destroy (c); + /* garbage collect */ gc_free (&c->c2.gc); } @@ -2922,6 +2937,7 @@ inherit_context_top (struct context *dest, dest->c2.event_set_owned = false; dest->c2.link_socket_owned = false; dest->c2.buffers_owned = false; + dest->c2.es_owned = false; dest->c2.event_set = NULL; if (src->options.proto == PROTO_UDPv4) diff --git a/misc.c b/misc.c index c6423fa80..a42ef24ea 100644 --- a/misc.c +++ b/misc.c @@ -690,13 +690,13 @@ add_env_item (char *str, const bool do_alloc, struct env_item **list, struct gc_ static bool env_set_del_nolock (struct env_set *es, const char *str) { - return remove_env_item (str, false, &es->list); + return remove_env_item (str, es->gc == NULL, &es->list); } static void env_set_add_nolock (struct env_set *es, const char *str) { - remove_env_item (str, false, &es->list); + remove_env_item (str, es->gc == NULL, &es->list); add_env_item ((char *)str, true, &es->list, es->gc); } @@ -704,7 +704,6 @@ struct env_set * env_set_create (struct gc_arena *gc) { struct env_set *es; - ASSERT (gc); mutex_lock_static (L_ENV_SET); ALLOC_OBJ_CLEAR_GC (es, struct env_set, gc); es->list = NULL; @@ -713,6 +712,25 @@ env_set_create (struct gc_arena *gc) return es; } +void +env_set_destroy (struct env_set *es) +{ + mutex_lock_static (L_ENV_SET); + if (es && es->gc == NULL) + { + struct env_item *e = es->list; + while (e) + { + struct env_item *next = e->next; + free (e->string); + free (e); + e = next; + } + free (es); + } + mutex_unlock_static (L_ENV_SET); +} + bool env_set_del (struct env_set *es, const char *str) { diff --git a/misc.h b/misc.h index ac761857b..d626dfefc 100644 --- a/misc.h +++ b/misc.h @@ -168,6 +168,7 @@ void setenv_del (struct env_set *es, const char *name); /* struct env_set functions */ struct env_set *env_set_create (struct gc_arena *gc); +void env_set_destroy (struct env_set *es); bool env_set_del (struct env_set *es, const char *str); void env_set_add (struct env_set *es, const char *str); diff --git a/openvpn.h b/openvpn.h index 2b6cf1461..0cdab624c 100644 --- a/openvpn.h +++ b/openvpn.h @@ -403,6 +403,7 @@ struct context_2 /* environmental variables to pass to scripts */ struct env_set *es; + bool es_owned; /* don't wait for TUN/TAP/UDP to be ready to accept write */ bool fast_io;