Cleanup ast_run_atexits() atexits list.

* Convert atexits list to a mutex instead of a rd/wr lock.  The lock is
only write locked.

* Move CLI verbose Asterisk ending message to where AMI message is output
in really_quit() to avoid further surprises about using stuff already
shutdown.

(issue ASTERISK-20649)
Reported by: Corey Farrell
........

Merged revisions 377165 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 377166 from http://svn.asterisk.org/svn/asterisk/branches/10


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/11@377167 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Richard Mudgett
2012-12-03 22:58:46 +00:00
parent 869c2b30c9
commit 656af72b89

View File

@@ -223,10 +223,10 @@ struct console {
struct ast_atexit { struct ast_atexit {
void (*func)(void); void (*func)(void);
AST_RWLIST_ENTRY(ast_atexit) list; AST_LIST_ENTRY(ast_atexit) list;
}; };
static AST_RWLIST_HEAD_STATIC(atexits, ast_atexit); static AST_LIST_HEAD_STATIC(atexits, ast_atexit);
struct timeval ast_startuptime; struct timeval ast_startuptime;
struct timeval ast_lastreloadtime; struct timeval ast_lastreloadtime;
@@ -964,39 +964,57 @@ 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)
{
struct ast_atexit *ae;
AST_LIST_LOCK(&atexits);
while ((ae = AST_LIST_REMOVE_HEAD(&atexits, list))) {
if (ae->func) {
ae->func();
}
ast_free(ae);
}
AST_LIST_UNLOCK(&atexits);
}
static void __ast_unregister_atexit(void (*func)(void))
{
struct ast_atexit *ae;
AST_LIST_TRAVERSE_SAFE_BEGIN(&atexits, ae, list) {
if (ae->func == func) {
AST_LIST_REMOVE_CURRENT(list);
ast_free(ae);
break;
}
}
AST_LIST_TRAVERSE_SAFE_END;
}
int ast_register_atexit(void (*func)(void)) int ast_register_atexit(void (*func)(void))
{ {
struct ast_atexit *ae; struct ast_atexit *ae;
if (!(ae = ast_calloc(1, sizeof(*ae)))) ae = ast_calloc(1, sizeof(*ae));
if (!ae) {
return -1; return -1;
}
ae->func = func; ae->func = func;
ast_unregister_atexit(func); AST_LIST_LOCK(&atexits);
__ast_unregister_atexit(func);
AST_RWLIST_WRLOCK(&atexits); AST_LIST_INSERT_HEAD(&atexits, ae, list);
AST_RWLIST_INSERT_HEAD(&atexits, ae, list); AST_LIST_UNLOCK(&atexits);
AST_RWLIST_UNLOCK(&atexits);
return 0; return 0;
} }
void ast_unregister_atexit(void (*func)(void)) void ast_unregister_atexit(void (*func)(void))
{ {
struct ast_atexit *ae = NULL; AST_LIST_LOCK(&atexits);
__ast_unregister_atexit(func);
AST_RWLIST_WRLOCK(&atexits); AST_LIST_UNLOCK(&atexits);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&atexits, ae, list) {
if (ae->func == func) {
AST_RWLIST_REMOVE_CURRENT(list);
break;
}
}
AST_RWLIST_TRAVERSE_SAFE_END;
AST_RWLIST_UNLOCK(&atexits);
free(ae);
} }
/* Sending commands from consoles back to the daemon requires a terminating NULL */ /* Sending commands from consoles back to the daemon requires a terminating NULL */
@@ -1665,17 +1683,6 @@ int ast_set_priority(int pri)
return 0; return 0;
} }
static void ast_run_atexits(void)
{
struct ast_atexit *ae;
AST_RWLIST_RDLOCK(&atexits);
AST_RWLIST_TRAVERSE(&atexits, ae, list) {
if (ae->func)
ae->func();
}
AST_RWLIST_UNLOCK(&atexits);
}
static int can_safely_quit(shutdown_nice_t niceness, int restart); 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);
@@ -1758,6 +1765,7 @@ static int can_safely_quit(shutdown_nice_t niceness, int restart)
return 1; return 1;
} }
/*! Called when exiting is certain. */
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;
@@ -1816,11 +1824,12 @@ static void really_quit(int num, shutdown_nice_t niceness, int restart)
"Restart: %s\r\n", "Restart: %s\r\n",
active_channels ? "Uncleanly" : "Cleanly", active_channels ? "Uncleanly" : "Cleanly",
restart ? "True" : "False"); restart ? "True" : "False");
ast_verb(0, "Asterisk %s ending (%d).\n",
active_channels ? "uncleanly" : "cleanly", num);
ast_verb(0, "Executing last minute cleanups\n"); ast_verb(0, "Executing last minute cleanups\n");
ast_run_atexits(); ast_run_atexits();
/* Called on exit */
ast_verb(0, "Asterisk %s ending (%d).\n", active_channels ? "uncleanly" : "cleanly", num);
ast_debug(1, "Asterisk ending (%d).\n", num); ast_debug(1, "Asterisk ending (%d).\n", num);
if (ast_socket > -1) { if (ast_socket > -1) {
pthread_cancel(lthread); pthread_cancel(lthread);