]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
main/formats: Fix crash in ast_format_cmp during non-clean shutdown.
authorCorey Farrell <git@cfware.com>
Thu, 27 Mar 2014 18:18:23 +0000 (18:18 +0000)
committerCorey Farrell <git@cfware.com>
Thu, 27 Mar 2014 18:18:23 +0000 (18:18 +0000)
* Backport ast_register_cleanup from Asterisk 12.
* Use ast_register_cleanup for format_attr_shutdown.

ast_register_cleanup was originally commited in r390122 by dlee.

(closes issue ASTERISK-23103)
Reported by: JoshE

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/11@411310 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk.h
main/asterisk.c
main/format.c

index 24e4c05128ddef94294d669dcbd4db12e1d17091..dc1e521bc6e067eff36ccd87b7c1acc4a4ec245a 100644 (file)
@@ -89,6 +89,22 @@ int ast_pbx_init(void);                              /*!< Provided by pbx.c */
  */
 int ast_register_atexit(void (*func)(void));
 
+/*!
+ * \since 11.9
+ * \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().
  * \param func The callback function to unregister.
index e8f1d41d57ed0731499a2a442d7b87fcae40ab32..c2a08a62a4ef60bf6550b81cc195f86f50d2ad04 100644 (file)
@@ -228,6 +228,7 @@ struct console {
 
 struct ast_atexit {
        void (*func)(void);
+       int is_cleanup;
        AST_LIST_ENTRY(ast_atexit) list;
 };
 
@@ -970,13 +971,13 @@ static char *handle_show_version_files(struct ast_cli_entry *e, int cmd, struct
 
 #endif /* ! LOW_MEMORY */
 
-static void ast_run_atexits(void)
+static void ast_run_atexits(int run_cleanups)
 {
        struct ast_atexit *ae;
 
        AST_LIST_LOCK(&atexits);
        while ((ae = AST_LIST_REMOVE_HEAD(&atexits, list))) {
-               if (ae->func) {
+               if (ae->func && (!ae->is_cleanup || run_cleanups)) {
                        ae->func();
                }
                ast_free(ae);
@@ -998,7 +999,7 @@ static void __ast_unregister_atexit(void (*func)(void))
        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;
 
@@ -1007,6 +1008,7 @@ int ast_register_atexit(void (*func)(void))
                return -1;
        }
        ae->func = func;
+       ae->is_cleanup = is_cleanup;
 
        AST_LIST_LOCK(&atexits);
        __ast_unregister_atexit(func);
@@ -1016,6 +1018,16 @@ int ast_register_atexit(void (*func)(void))
        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))
 {
        AST_LIST_LOCK(&atexits);
@@ -1802,8 +1814,9 @@ static int can_safely_quit(shutdown_nice_t niceness, int restart)
 static void really_quit(int num, shutdown_nice_t niceness, int restart)
 {
        int active_channels;
+       int run_cleanups = niceness >= SHUTDOWN_NICE;
 
-       if (niceness >= SHUTDOWN_NICE) {
+       if (run_cleanups) {
                ast_module_shutdown();
        }
 
@@ -1861,7 +1874,7 @@ static void really_quit(int num, shutdown_nice_t niceness, int restart)
                active_channels ? "uncleanly" : "cleanly", num);
 
        ast_verb(0, "Executing last minute cleanups\n");
-       ast_run_atexits();
+       ast_run_atexits(run_cleanups);
 
        ast_debug(1, "Asterisk ending (%d).\n", num);
        if (ast_socket > -1) {
index d7fa744fb8b94b0c4b2d440a46cefd3d5255b494..adf4151c9fd69b45b8c8fc0d87ddb32b5f6390ed 100644 (file)
@@ -1128,7 +1128,7 @@ int ast_format_attr_init(void)
        }
 
        ast_cli_register_multiple(my_clis, ARRAY_LEN(my_clis));
-       ast_register_atexit(format_attr_shutdown);
+       ast_register_cleanup(format_attr_shutdown);
        return 0;
 }