autoservice: stop thread on graceful shutdown

This change adds thread shutdown to autoservice for graceful shutdowns only.
ast_register_cleanup is backported to 1.8 to allow this.  The logger callid
is also released on shutdown in 11+.

ASTERISK-23827 #close
Reported by: Corey Farrell
Review: https://reviewboard.asterisk.org/r/3594/


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@415463 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Corey Farrell
2014-06-09 03:43:21 +00:00
parent 560380a018
commit 1dff17f051
3 changed files with 48 additions and 6 deletions

View File

@@ -89,6 +89,22 @@ int ast_pbx_init(void); /*!< Provided by pbx.c */
*/ */
int ast_register_atexit(void (*func)(void)); int ast_register_atexit(void (*func)(void));
/*!
* \since 1.8.29
* \brief Register a function to be executed before Asterisk gracefully exits.
*
* If Asterisk is immediately shutdown (core stop now, or sending the TERM
* signal), the callback is not run. When the callbacks are run, they are run in
* sequence with ast_register_atexit() callbacks, in the reverse order of
* registration.
*
* \param func The callback function to use.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_register_cleanup(void (*func)(void));
/*! /*!
* \brief Unregister a function registered with ast_register_atexit(). * \brief Unregister a function registered with ast_register_atexit().
* \param func The callback function to unregister. * \param func The callback function to unregister.

View File

@@ -209,6 +209,7 @@ struct console {
struct ast_atexit { struct ast_atexit {
void (*func)(void); void (*func)(void);
int is_cleanup;
AST_LIST_ENTRY(ast_atexit) list; AST_LIST_ENTRY(ast_atexit) list;
}; };
@@ -944,13 +945,13 @@ static char *handle_show_version_files(struct ast_cli_entry *e, int cmd, struct
#endif /* ! LOW_MEMORY */ #endif /* ! LOW_MEMORY */
static void ast_run_atexits(void) static void ast_run_atexits(int run_cleanups)
{ {
struct ast_atexit *ae; struct ast_atexit *ae;
AST_LIST_LOCK(&atexits); AST_LIST_LOCK(&atexits);
while ((ae = AST_LIST_REMOVE_HEAD(&atexits, list))) { while ((ae = AST_LIST_REMOVE_HEAD(&atexits, list))) {
if (ae->func) { if (ae->func && (!ae->is_cleanup || run_cleanups)) {
ae->func(); ae->func();
} }
ast_free(ae); ast_free(ae);
@@ -972,7 +973,7 @@ static void __ast_unregister_atexit(void (*func)(void))
AST_LIST_TRAVERSE_SAFE_END; AST_LIST_TRAVERSE_SAFE_END;
} }
int ast_register_atexit(void (*func)(void)) static int register_atexit(void (*func)(void), int is_cleanup)
{ {
struct ast_atexit *ae; struct ast_atexit *ae;
@@ -981,6 +982,7 @@ int ast_register_atexit(void (*func)(void))
return -1; return -1;
} }
ae->func = func; ae->func = func;
ae->is_cleanup = is_cleanup;
AST_LIST_LOCK(&atexits); AST_LIST_LOCK(&atexits);
__ast_unregister_atexit(func); __ast_unregister_atexit(func);
@@ -990,6 +992,16 @@ int ast_register_atexit(void (*func)(void))
return 0; return 0;
} }
int ast_register_atexit(void (*func)(void))
{
return register_atexit(func, 0);
}
int ast_register_cleanup(void (*func)(void))
{
return register_atexit(func, 1);
}
void ast_unregister_atexit(void (*func)(void)) void ast_unregister_atexit(void (*func)(void))
{ {
AST_LIST_LOCK(&atexits); AST_LIST_LOCK(&atexits);
@@ -1748,8 +1760,9 @@ static int can_safely_quit(shutdown_nice_t niceness, int restart)
static void really_quit(int num, shutdown_nice_t niceness, int restart) static void really_quit(int num, shutdown_nice_t niceness, int restart)
{ {
int active_channels; int active_channels;
int run_cleanups = niceness >= SHUTDOWN_NICE;
if (niceness >= SHUTDOWN_NICE) { if (run_cleanups) {
ast_module_shutdown(); ast_module_shutdown();
} }
@@ -1791,7 +1804,7 @@ static void really_quit(int num, shutdown_nice_t niceness, int restart)
if (option_verbose) if (option_verbose)
ast_verbose("Executing last minute cleanups\n"); ast_verbose("Executing last minute cleanups\n");
ast_run_atexits(); ast_run_atexits(run_cleanups);
ast_debug(1, "Asterisk ending (%d).\n", num); ast_debug(1, "Asterisk ending (%d).\n", num);
if (ast_socket > -1) { if (ast_socket > -1) {

View File

@@ -72,6 +72,7 @@ static AST_LIST_HEAD_STATIC(aslist, asent);
static ast_cond_t as_cond; static ast_cond_t as_cond;
static pthread_t asthread = AST_PTHREADT_NULL; static pthread_t asthread = AST_PTHREADT_NULL;
static volatile int asexit = 0;
static int as_chan_list_state; static int as_chan_list_state;
@@ -82,7 +83,7 @@ static void *autoservice_run(void *ign)
.subclass.integer = AST_CONTROL_HANGUP, .subclass.integer = AST_CONTROL_HANGUP,
}; };
for (;;) { while (!asexit) {
struct ast_channel *mons[MAX_AUTOMONS]; struct ast_channel *mons[MAX_AUTOMONS];
struct asent *ents[MAX_AUTOMONS]; struct asent *ents[MAX_AUTOMONS];
struct ast_channel *chan; struct ast_channel *chan;
@@ -320,7 +321,19 @@ int ast_autoservice_ignore(struct ast_channel *chan, enum ast_frame_type ftype)
return res; return res;
} }
static void autoservice_shutdown(void)
{
pthread_t th = asthread;
asexit = 1;
if (th != AST_PTHREADT_NULL) {
ast_cond_signal(&as_cond);
pthread_kill(th, SIGURG);
pthread_join(th, NULL);
}
}
void ast_autoservice_init(void) void ast_autoservice_init(void)
{ {
ast_register_cleanup(autoservice_shutdown);
ast_cond_init(&as_cond, NULL); ast_cond_init(&as_cond, NULL);
} }