]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Fix shutdown crash caused by modules being left open. 14/4214/1
authorCorey Farrell <git@cfware.com>
Fri, 28 Oct 2016 02:49:43 +0000 (22:49 -0400)
committerCorey Farrell <git@cfware.com>
Fri, 28 Oct 2016 05:11:21 +0000 (01:11 -0400)
It is only safe to run ast_register_cleanup callbacks when all modules
have been unloaded.  Previously these callbacks were run during graceful
shutdown, making it possible to crash during shutdown.

ASTERISK-26513 #close

Change-Id: Ibfa635bb688d1227ec54aa211d90d6bd45052e21

include/asterisk/_private.h
include/asterisk/module.h
main/asterisk.c
main/loader.c

index 9255dc1defcca4aecc29360d22b23eadf6f1d6e6..d4a0d725124b14f4abe068f50b258efac5224937 100644 (file)
@@ -16,6 +16,7 @@
 #define _ASTERISK__PRIVATE_H
 
 int load_modules(unsigned int);                /*!< Provided by loader.c */
+int modules_shutdown(void);            /*!< Provided by loader.c */
 int load_pbx(void);                    /*!< Provided by pbx.c */
 int load_pbx_builtins(void);   /*!< Provided by pbx_builtins.c */
 int load_pbx_functions_cli(void);      /*!< Provided by pbx_functions.c */
index 35ee8bbd76c78e4059710626cfd3058fb28910e8..b92043b8465c6ec362ee43f3fed367b139ad384d 100644 (file)
@@ -228,13 +228,6 @@ int ast_loader_register(int (*updater)(void));
  */
 int ast_loader_unregister(int (*updater)(void));
 
-/*!
- * \brief Run the unload() callback for all loaded modules
- *
- * This function should be called when Asterisk is shutting down gracefully.
- */
-void ast_module_shutdown(void);
-
 /*! 
  * \brief Match modules names for the Asterisk cli.
  * \param line Unused by this function, but this should be the line we are
index 92993d34f3bdd8666325bb88328a7f9eba0c2b36..de00f4faa50132973b77997e4ea0a860b2d5189b 100644 (file)
@@ -2140,8 +2140,9 @@ static void really_quit(int num, shutdown_nice_t niceness, int restart)
        struct ast_json *json_object = NULL;
        int run_cleanups = niceness >= SHUTDOWN_NICE;
 
-       if (run_cleanups) {
-               ast_module_shutdown();
+       if (run_cleanups && modules_shutdown()) {
+               ast_verb(0, "Some modules could not be unloaded, switching to fast shutdown\n");
+               run_cleanups = 0;
        }
 
        if (!restart) {
index 85aeb249e1d1a99abe80ea8b2cefadda67533e5a..74254b4fa55dbccf70a0b8a0314cbd2b2fab994a 100644 (file)
@@ -613,7 +613,7 @@ static struct ast_module *load_dynamic_module(const char *resource_in, unsigned
 
 #endif
 
-void ast_module_shutdown(void)
+int modules_shutdown(void)
 {
        struct ast_module *mod;
        int somethingchanged = 1, final = 0;
@@ -663,7 +663,10 @@ void ast_module_shutdown(void)
                }
        } while (somethingchanged && !final);
 
+       final = AST_DLLIST_EMPTY(&module_list);
        AST_DLLIST_UNLOCK(&module_list);
+
+       return !final;
 }
 
 int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode force)