Add a new libevent_global_shutdown() to free all globals before exiting.

Mark Ellzey added a function libevent_shutdown() which calls a set of
private functions:

       * event_free_globals()
       * event_free_debug_globals()
       * event_free_debug_globals_locks()
       * event_free_evsig_globals()
       * evsig_free_globals()
       * evsig_free_globals_locks()
       * evutil_free_globals()
       * evutil_free_secure_rng_globals()
       * evutil_free_secure_rng_globals_lock()

Nick tweaked this libevent global shutdown code:

  - rename the function to emphasize that it's for global resources
  - write more in the doxygen
  - make function brace style consistent
  - add a missing void in a function definition.
This commit is contained in:
Mark Ellzey 2011-07-12 12:25:41 -04:00 committed by Nick Mathewson
parent 24dab0b359
commit 041ca00c75
8 changed files with 107 additions and 0 deletions

45
event.c
View File

@ -3124,6 +3124,51 @@ event_base_del_virtual_(struct event_base *base)
EVBASE_RELEASE_LOCK(base, th_base_lock); EVBASE_RELEASE_LOCK(base, th_base_lock);
} }
static void
event_free_debug_globals_locks(void)
{
#ifndef EVENT__DISABLE_THREAD_SUPPORT
#ifndef EVENT__DISABLE_DEBUG_MODE
if (event_debug_map_lock_ != NULL) {
EVTHREAD_FREE_LOCK(event_debug_map_lock_, 0);
}
#endif /* EVENT__DISABLE_DEBUG_MODE */
#endif /* EVENT__DISABLE_THREAD_SUPPORT */
return;
}
static void
event_free_debug_globals(void)
{
event_free_debug_globals_locks();
}
static void
event_free_evsig_globals(void)
{
evsig_free_globals_();
}
static void
event_free_evutil_globals(void)
{
evutil_free_globals_();
}
static void
event_free_globals(void)
{
event_free_debug_globals();
event_free_evsig_globals();
event_free_evutil_globals();
}
void
libevent_global_shutdown(void)
{
event_free_globals();
}
#ifndef EVENT__DISABLE_THREAD_SUPPORT #ifndef EVENT__DISABLE_THREAD_SUPPORT
int int
event_global_setup_locks_(const int enable_locks) event_global_setup_locks_(const int enable_locks)

View File

@ -60,5 +60,6 @@ int evsig_init_(struct event_base *);
void evsig_dealloc_(struct event_base *); void evsig_dealloc_(struct event_base *);
void evsig_set_base_(struct event_base *base); void evsig_set_base_(struct event_base *base);
void evsig_free_globals_(void);
#endif /* EVSIGNAL_INTERNAL_H_INCLUDED_ */ #endif /* EVSIGNAL_INTERNAL_H_INCLUDED_ */

View File

@ -2543,3 +2543,8 @@ evutil_eventfd_(unsigned initval, int flags)
#endif #endif
} }
void
evutil_free_globals_(void)
{
evutil_free_secure_rng_globals_();
}

View File

@ -50,11 +50,13 @@ evutil_secure_rng_init(void)
(void) arc4random(); (void) arc4random();
return 0; return 0;
} }
#ifndef EVENT__DISABLE_THREAD_SUPPORT
int int
evutil_secure_rng_global_setup_locks_(const int enable_locks) evutil_secure_rng_global_setup_locks_(const int enable_locks)
{ {
return 0; return 0;
} }
#endif
static void static void
ev_arc4random_buf(void *buf, size_t n) ev_arc4random_buf(void *buf, size_t n)
@ -112,6 +114,22 @@ evutil_secure_rng_global_setup_locks_(const int enable_locks)
} }
#endif #endif
static void
evutil_free_secure_rng_globals_locks(void)
{
#ifndef EVENT__DISABLE_THREAD_SUPPORT
if (arc4rand_lock != NULL) {
EVTHREAD_FREE_LOCK(arc4rand_lock, 0);
}
#endif
return;
}
void
evutil_free_secure_rng_globals_(void) {
{
evutil_free_secure_rng_globals_locks();
}
int int
evutil_secure_rng_init(void) evutil_secure_rng_init(void)
{ {

View File

@ -1310,6 +1310,22 @@ int event_base_gettimeofday_cached(struct event_base *base,
*/ */
int event_base_update_cache_time(struct event_base *base); int event_base_update_cache_time(struct event_base *base);
/** Release up all globally-allocated resources allocated by Libevent.
This function does not free developer-controlled resources like
event_bases, events, bufferevents, listeners, and so on. It only releases
resources like global locks that there is no other way to free.
It is not actually necessary to call this function before exit: every
resource that it frees would be released anyway on exit. It mainly exists
so that resource-leak debugging tools don't see Libevent as holding
resources at exit.
You should only call this function when no other Libevent functions will
be invoked -- e.g., when cleanly exiting a program.
*/
void libevent_global_shutdown(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -156,6 +156,7 @@ main(int argc, char **argv)
close(socket); close(socket);
unlink(fifo); unlink(fifo);
#endif #endif
libevent_global_shutdown();
return (0); return (0);
} }

View File

@ -449,6 +449,23 @@ evsig_dealloc_(struct event_base *base)
} }
} }
static void
evsig_free_globals_locks(void)
{
#ifndef EVENT__DISABLE_THREAD_SUPPORT
if (evsig_base_lock != NULL) {
EVTHREAD_FREE_LOCK(evsig_base_lock, 0);
}
#endif
return;
}
void
evsig_free_globals_(void)
{
evsig_free_globals_locks();
}
#ifndef EVENT__DISABLE_THREAD_SUPPORT #ifndef EVENT__DISABLE_THREAD_SUPPORT
int int
evsig_global_setup_locks_(const int enable_locks) evsig_global_setup_locks_(const int enable_locks)
@ -456,4 +473,5 @@ evsig_global_setup_locks_(const int enable_locks)
EVTHREAD_SETUP_GLOBAL_LOCK(evsig_base_lock, 0); EVTHREAD_SETUP_GLOBAL_LOCK(evsig_base_lock, 0);
return 0; return 0;
} }
#endif #endif

View File

@ -347,6 +347,9 @@ int evutil_hex_char_to_int_(char c);
void evutil_usleep_(const struct timeval *tv); void evutil_usleep_(const struct timeval *tv);
void evutil_free_secure_rng_globals_(void);
void evutil_free_globals_(void);
#ifdef _WIN32 #ifdef _WIN32
HANDLE evutil_load_windows_system_library_(const TCHAR *library_name); HANDLE evutil_load_windows_system_library_(const TCHAR *library_name);
#endif #endif