2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Asterisk  - -  An  open  source  telephony  toolkit . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Copyright  ( C )  1999  -  2006 ,  Digium ,  Inc . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Mark  Spencer  < markster @ digium . com > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Kevin  P .  Fleming  < kpfleming @ digium . com > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Luigi  Rizzo  < rizzo @ icir . org > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  See  http : //www.asterisk.org for more information about
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  Asterisk  project .  Please  do  not  directly  contact 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  any  of  the  maintainers  of  this  project  for  assistance ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  project  provides  a  web  site ,  mailing  lists  and  IRC 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  channels  for  your  use . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  program  is  free  software ,  distributed  under  the  terms  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  GNU  General  Public  License  Version  2.  See  the  LICENSE  file 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  at  the  top  of  the  source  tree . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \file
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Module  Loader 
							 
						 
					
						
							
								
									
										
										
										
											2006-09-15 05:00:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ author  Mark  Spencer  < markster @ digium . com > 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 *  \ author  Kevin  P .  Fleming  < kpfleming @ digium . com > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ author  Luigi  Rizzo  < rizzo @ icir . org > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  -  See  ModMngMnt 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-06-15 16:20:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*** MODULEINFO
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< support_level > core < / support_level > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * * */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# include  "asterisk.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-11-20 22:18:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/_private.h" 
  
						 
					
						
							
								
									
										
										
										
											2007-11-20 23:16:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/paths.h"	/* use ast_config_AST_MODULE_DIR */ 
  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# include  <dirent.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/dlinkedlists.h" 
  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/module.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/config.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/channel.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/term.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/manager.h" 
  
						 
					
						
							
								
									
										
										
										
											2018-02-16 22:11:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/io.h" 
  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/lock.h" 
  
						 
					
						
							
								
									
										
										
										
											2017-11-21 01:28:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/vector.h" 
  
						 
					
						
							
								
									
										
										
										
											2010-01-27 18:29:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/app.h" 
  
						 
					
						
							
								
									
										
										
										
											2012-08-13 20:36:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/test.h" 
  
						 
					
						
							
								
									
										
										
										
											2018-01-25 13:06:12 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/cli.h" 
  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <dlfcn.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/md5.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/utils.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-07-11 02:06:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*** DOCUMENTATION
  
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									< managerEvent  language = " en_US "  name = " Reload " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< managerEventInstance  class = " EVENT_FLAG_SYSTEM " > 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-23 16:35:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											< since > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< version > 12.0 .0 < / version > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / since > 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											< synopsis > Raised  when  a  module  has  been  reloaded  in  Asterisk . < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< parameter  name = " Module " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< para > The  name  of  the  module  that  was  reloaded ,  or 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< literal > All < / literal >  if  all  modules  were  reloaded < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / parameter > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< parameter  name = " Status " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< para > The  numeric  status  code  denoting  the  success  or  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													of  the  reload  request . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< enumlist > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														< enum  name = " 0 " > < para > Success < / para > < / enum > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														< enum  name = " 1 " > < para > Request  queued < / para > < / enum > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														< enum  name = " 2 " > < para > Module  not  found < / para > < / enum > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														< enum  name = " 3 " > < para > Error < / para > < / enum > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														< enum  name = " 4 " > < para > Reload  already  in  progress < / para > < / enum > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														< enum  name = " 5 " > < para > Module  uninitialized < / para > < / enum > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														< enum  name = " 6 " > < para > Reload  not  supported < / para > < / enum > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< / enumlist > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / parameter > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / managerEventInstance > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< / managerEvent > 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-06 21:27:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									< managerEvent  language = " en_US "  name = " Load " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< managerEventInstance  class = " EVENT_FLAG_SYSTEM " > 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-23 16:35:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											< since > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< version > 16.0 .0 < / version > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / since > 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-06 21:27:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											< synopsis > Raised  when  a  module  has  been  loaded  in  Asterisk . < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< parameter  name = " Module " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< para > The  name  of  the  module  that  was  loaded < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / parameter > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< parameter  name = " Status " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< para > The  result  of  the  load  request . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< enumlist > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														< enum  name = " Failure " > < para > Module  could  not  be  loaded  properly < / para > < / enum > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														< enum  name = " Success " > < para > Module  loaded  and  configured < / para > < / enum > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														< enum  name = " Decline " > < para > Module  is  not  configured < / para > < / enum > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< / enumlist > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / parameter > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / managerEventInstance > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< / managerEvent > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< managerEvent  language = " en_US "  name = " Unload " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< managerEventInstance  class = " EVENT_FLAG_SYSTEM " > 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-23 16:35:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											< since > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< version > 16.0 .0 < / version > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / since > 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-06 21:27:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											< synopsis > Raised  when  a  module  has  been  unloaded  in  Asterisk . < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< parameter  name = " Module " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< para > The  name  of  the  module  that  was  unloaded < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / parameter > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< parameter  name = " Status " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< para > The  result  of  the  unload  request . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< enumlist > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														< enum  name = " Success " > < para > Module  unloaded  successfully < / para > < / enum > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< / enumlist > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / parameter > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / managerEventInstance > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< / managerEvent > 
							 
						 
					
						
							
								
									
										
										
										
											2012-07-11 02:06:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * * */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-22 14:56:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# ifndef RTLD_NOW 
  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# define RTLD_NOW 0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-11-17 09:51:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# ifndef RTLD_LOCAL 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define RTLD_LOCAL 0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								struct  ast_module_user  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel  * chan ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_ENTRY ( ast_module_user )  entry ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								AST_DLLIST_HEAD ( module_user_list ,  ast_module_user ) ;  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-05-21 21:13:09 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  const  unsigned  char  expected_key [ ]  =  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  0x87 ,  0x76 ,  0x79 ,  0x35 ,  0x23 ,  0xea ,  0x3a ,  0xd3 ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  0x25 ,  0x2a ,  0xbb ,  0x35 ,  0x87 ,  0xe4 ,  0x22 ,  0x24  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-11-20 19:28:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  char  buildopt_sum [ 33 ]  =  AST_BUILDOPT_SUM ;  
						 
					
						
							
								
									
										
										
										
											2007-11-16 16:56:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 01:28:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								AST_VECTOR ( module_vector ,  struct  ast_module  * ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! Used with AST_VECTOR_CALLBACK_VOID to create a
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  comma  separated  list  of  module  names  for  error  messages .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define STR_APPEND_TEXT(txt, str) \ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_str_append ( str ,  0 ,  " %s%s " ,  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_str_strlen ( * ( str ) )  >  0  ?  " ,  "  :  " " ,  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										txt ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-29 23:00:52 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* Built-in module registrations need special handling at startup */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  unsigned  int  loader_ready ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! String container for deferring output of startup errors. */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ast_vector_string  startup_errors ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ast_str  * startup_error_builder ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-10 11:03:11 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# if defined(HAVE_PERMANENT_DLOPEN) || defined(AST_XML_DOCS) 
  
						 
					
						
							
								
									
										
										
										
											2019-04-02 22:49:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  char  * get_name_from_resource ( const  char  * resource )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * last_three ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * mod_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! resource )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									len  =  strlen ( resource ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( len  >  3 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										last_three  =  & resource [ len - 3 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strcasecmp ( last_three ,  " .so " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											mod_name  =  ast_calloc ( 1 ,  len  -  2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( mod_name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_copy_string ( mod_name ,  resource ,  len  -  2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  mod_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* Unable to allocate memory. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Resource is the name - happens when manually unloading a module. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mod_name  =  ast_calloc ( 1 ,  len  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( mod_name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( mod_name ,  resource ,  len  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  mod_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Unable to allocate memory. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2021-03-10 11:03:11 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(HAVE_PERMANENT_DLOPEN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define FIRST_DLOPEN 999 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  ao2_container  * info_list  =  NULL ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  info_list_obj  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  ast_module_info  * info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  dlopened ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  name [ 0 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  info_list_obj  * info_list_obj_alloc ( const  char  * name ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  ast_module_info  * info ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  info_list_obj  * new_entry ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									new_entry  =  ao2_alloc ( sizeof ( * new_entry )  +  strlen ( name )  +  1 ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! new_entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									strcpy ( new_entry - > name ,  name ) ;  /* SAFE */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									new_entry - > info  =  info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									new_entry - > dlopened  =  FIRST_DLOPEN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  new_entry ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AO2_STRING_FIELD_CMP_FN ( info_list_obj ,  name )  
						 
					
						
							
								
									
										
										
										
											2019-04-02 22:49:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  manual_mod_reg ( const  void  * lib ,  const  char  * resource )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  info_list_obj  * obj_tmp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * mod_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( lib )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mod_name  =  get_name_from_resource ( resource ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( mod_name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											obj_tmp  =  ao2_find ( info_list ,  mod_name ,  OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( obj_tmp )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( obj_tmp - > dlopened  = =  FIRST_DLOPEN )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													obj_tmp - > dlopened  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ast_module_register ( obj_tmp - > info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ao2_ref ( obj_tmp ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_free ( mod_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  manual_mod_unreg ( const  char  * resource )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  info_list_obj  * obj_tmp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * mod_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* When Asterisk shuts down the destructor is called automatically. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_shutdown_final ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mod_name  =  get_name_from_resource ( resource ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( mod_name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										obj_tmp  =  ao2_find ( info_list ,  mod_name ,  OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( obj_tmp )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_module_unregister ( obj_tmp - > info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_ref ( obj_tmp ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_free ( mod_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  __attribute__ ( ( format ( printf ,  1 ,  2 ) ) )  void  module_load_error ( const  char  * fmt ,  . . . )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * copy  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									va_list  ap ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									va_start ( ap ,  fmt ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( startup_error_builder )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_str_set_va ( & startup_error_builder ,  0 ,  fmt ,  ap ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										copy  =  ast_strdup ( ast_str_buffer ( startup_error_builder ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! copy  | |  AST_VECTOR_APPEND ( & startup_errors ,  copy ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_ERROR ,  " %s " ,  ast_str_buffer ( startup_error_builder ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_free ( copy ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log_ap ( LOG_ERROR ,  fmt ,  ap ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									va_end ( ap ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-04-09 23:08:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Internal  flag  to  indicate  all  modules  have  been  initially  loaded . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  modules_loaded ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								struct  ast_module  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  ast_module_info  * info ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-19 22:23:44 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*! Used to get module references into refs log */ 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-11 17:03:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									void  * ref_debug ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-19 22:23:44 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*! The shared lib. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * lib ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Number of 'users' and other references currently holding the module. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  usecount ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! List of users holding the module. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  module_user_list  users ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! List of required module names. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_vector_string  requires ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! List of optional api modules. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_vector_string  optional_modules ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! List of modules this enhances. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_vector_string  enhances ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ brief  Vector  holding  pointers  to  modules  we  have  a  reference  to . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  When  one  module  requires  another ,  the  required  module  gets  added 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  to  this  list  with  a  reference . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  module_vector  reffed_deps ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-03 16:43:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-19 22:23:44 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/*! The module running and ready to accept requests. */ 
							 
						 
					
						
							
								
									
										
										
											
												After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@75983 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2007-07-19 23:24:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										unsigned  int  running : 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-19 22:23:44 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/*! The module has declined to start. */ 
							 
						 
					
						
							
								
									
										
										
											
												After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@75983 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2007-07-19 23:24:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										unsigned  int  declined : 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-19 22:23:44 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/*! This module is being held open until it's time to shutdown. */ 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-11 17:03:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										unsigned  int  keepuntilshutdown : 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-29 23:00:52 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/*! The module is built-in. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unsigned  int  builtin : 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/*! The admin has declared this module is required. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unsigned  int  required : 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*! This module is marked for preload. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unsigned  int  preload : 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-03 16:43:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  flags ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_ENTRY ( ast_module )  entry ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									char  resource [ 0 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  AST_DLLIST_HEAD_STATIC ( module_list ,  ast_module ) ;  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-06 21:27:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  load_results_map  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  const  struct  load_results_map  load_results [ ]  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  AST_MODULE_LOAD_SUCCESS ,  " Success "  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  AST_MODULE_LOAD_DECLINE ,  " Decline "  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  AST_MODULE_LOAD_SKIP ,  " Skip "  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  AST_MODULE_LOAD_PRIORITY ,  " Priority "  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  AST_MODULE_LOAD_FAILURE ,  " Failure "  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define AST_MODULE_LOAD_UNKNOWN_STRING		"Unknown"		 /* Status string for unknown load status */ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  publish_load_message_type ( const  char *  type ,  const  char  * name ,  const  char  * status ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  publish_reload_message ( const  char  * name ,  enum  ast_module_reload_result  result ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  publish_load_message ( const  char  * name ,  enum  ast_module_load_result  result ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  publish_unload_message ( const  char  * name ,  const  char *  status ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-29 23:00:52 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  module_list  is  cleared  by  its  constructor  possibly  after 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  we  start  accumulating  built - in  modules ,  so  we  need  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  use  another  list  ( without  the  lock )  to  accumulate  them . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  module_list  builtin_module_list ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  module_vector_strcasecmp ( struct  ast_module  * a ,  struct  ast_module  * b )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  strcasecmp ( a - > resource ,  b - > resource ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 01:28:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  module_vector_cmp ( struct  ast_module  * a ,  struct  ast_module  * b )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  preload_diff  =  ( int ) b - > flags . preload  -  ( int ) a - > flags . preload ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 01:28:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* if load_pri is not set, default is 128.  Lower is better */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  a_pri  =  ast_test_flag ( a - > info ,  AST_MODFLAG_LOAD_ORDER ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										?  a - > info - > load_pri  :  AST_MODPRI_DEFAULT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  b_pri  =  ast_test_flag ( b - > info ,  AST_MODFLAG_LOAD_ORDER ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										?  b - > info - > load_pri  :  AST_MODPRI_DEFAULT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( preload_diff )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* -1 preload a but not b */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*  0 preload both or neither */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*  1 preload b but not a */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  preload_diff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 01:28:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Returns  comparison  values  for  a  vector  sorted  by  priority . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  < 0  a_pri  <  b_pri 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  = 0  a_pri  = =  b_pri 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  > 0  a_pri  >  b_pri 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  a_pri  -  b_pri ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  struct  ast_module  * find_resource ( const  char  * resource ,  int  do_lock ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Add  a  reference  from  mod  to  dep . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  mod  Owner  of  the  new  reference . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  dep  Module  to  reference 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  missing  Vector  to  store  name  of  \ a  dep  if  it  is  not  running . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  function  returns  failure  if  \ a  dep  is  not  running  and  \ a  missing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  is  NULL .   If  \ a  missing  is  not  NULL  errors  will  only  be  returned  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  allocation  failures . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  Success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  Failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  Adding  a  second  reference  to  the  same  dep  will  return  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *        without  doing  anything . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  module_reffed_deps_add ( struct  ast_module  * mod ,  struct  ast_module  * dep ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_vector_const_string  * missing ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! dep - > flags . running )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ! missing  ?  - 1  :  AST_VECTOR_APPEND ( missing ,  dep - > info - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( AST_VECTOR_GET_CMP ( & mod - > reffed_deps ,  dep ,  AST_VECTOR_ELEM_DEFAULT_CMP ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Skip duplicate. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( AST_VECTOR_APPEND ( & mod - > reffed_deps ,  dep ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_module_ref ( dep ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Add  references  for  modules  that  enhance  a  dependency . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  mod  Owner  of  the  new  references . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  dep  Module  to  check  for  enhancers . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  missing  Vector  to  store  name  of  any  enhancer  that  is  not  running  or  declined . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  Success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  Failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  module_reffed_deps_add_dep_enhancers ( struct  ast_module  * mod ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module  * dep ,  struct  ast_vector_const_string  * missing ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module  * cur ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_TRAVERSE ( & module_list ,  cur ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cur - > flags . declined )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! AST_VECTOR_GET_CMP ( & cur - > enhances ,  dep - > info - > name ,  ! strcasecmp ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* dep is not enhanced by cur. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* dep is enhanced by cur, therefore mod requires cur. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( module_reffed_deps_add ( mod ,  cur ,  missing ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Add  references  to  a  list  of  dependencies . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  mod  Owner  of  the  new  references . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  vec  List  of  required  modules  to  process 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  missing  Vector  to  store  names  of  modules  that  are  not  running . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  ref_enhancers  Reference  all  enhancers  of  each  required  module . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  isoptional  Modules  that  are  not  loaded  can  be  ignored . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  Success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  Failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  module_deps_process_reqlist ( struct  ast_module  * mod ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_vector_string  * vec ,  struct  ast_vector_const_string  * missing , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ref_enhancers ,  int  isoptional ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( idx  =  0 ;  idx  <  AST_VECTOR_SIZE ( vec ) ;  idx + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  char  * depname  =  AST_VECTOR_GET ( vec ,  idx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_module  * dep  =  find_resource ( depname ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! dep  | |  ! dep - > flags . running )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( isoptional  & &  ! dep )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( missing  & &  ! AST_VECTOR_APPEND ( missing ,  depname ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( module_reffed_deps_add ( mod ,  dep ,  missing ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ref_enhancers  & &  module_reffed_deps_add_dep_enhancers ( mod ,  dep ,  missing ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Grab  all  references  required  to  start  the  module . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  mod  The  module  we ' re  trying  to  start . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  missing  Vector  to  store  a  list  of  missing  dependencies . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  Success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  Failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  module_list  must  be  locked . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  Caller  is  responsible  for  initializing  and  freeing  the  vector . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *        Elements  are  safely  read  only  while  module_list  remains  locked . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  module_deps_reference ( struct  ast_module  * mod ,  struct  ast_vector_const_string  * missing )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Grab references to modules we enhance but not other enhancements. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  | =  module_deps_process_reqlist ( mod ,  & mod - > enhances ,  missing ,  0 ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Grab references to modules we require plus enhancements. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  | =  module_deps_process_reqlist ( mod ,  & mod - > requires ,  missing ,  1 ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Grab references to optional modules including enhancements. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  | =  module_deps_process_reqlist ( mod ,  & mod - > optional_modules ,  missing ,  1 ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Recursively  find  required  dependencies  that  are  not  running . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  mod  Module  to  scan  for  dependencies . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  missingdeps  Vector  listing  modules  that  must  be  started  first . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  All  dependencies  resolved . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  Failed  to  resolve  some  dependencies . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  An  error  from  this  function  usually  means  a  required  module  is  not  even 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  loaded .   This  function  is  safe  from  infinite  recursion ,  but  dependency 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  loops  are  not  reported  as  an  error  from  here .   On  success  missingdeps 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  will  contain  a  list  of  every  module  that  needs  to  be  running  before  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  module  can  start .   missingdeps  is  sorted  by  load  priority  so  any  missing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  dependencies  can  be  started  if  needed . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  module_deps_missing_recursive ( struct  ast_module  * mod ,  struct  module_vector  * missingdeps )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_vector_const_string  localdeps ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module  * dep ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  localdeps  stores  a  copy  of  all  dependencies  that  mod  could  not  reference . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  First  we  discard  modules  that  we ' ve  already  found .  We  add  all  newly  found 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  modules  to  the  missingdeps  vector  then  scan  them  recursively .   This  will 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  ensure  we  quickly  run  out  of  stuff  to  do . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_INIT ( & localdeps ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( module_deps_reference ( mod ,  & localdeps ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  clean_return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( i  <  AST_VECTOR_SIZE ( & localdeps ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dep  =  find_resource ( AST_VECTOR_GET ( & localdeps ,  i ) ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! dep )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  clean_return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( AST_VECTOR_GET_CMP ( missingdeps ,  dep ,  AST_VECTOR_ELEM_DEFAULT_CMP ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Skip common dependency.  We have already searched it. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_VECTOR_REMOVE ( & localdeps ,  i ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* missingdeps is the real list so keep it sorted. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( AST_VECTOR_ADD_SORTED ( missingdeps ,  dep ,  module_vector_cmp ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												goto  clean_return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											i + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  ! res  & &  i  <  AST_VECTOR_SIZE ( & localdeps ) ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dep  =  find_resource ( AST_VECTOR_GET ( & localdeps ,  i ) ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* We've already confirmed dep is loaded in the first loop. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  module_deps_missing_recursive ( dep ,  missingdeps ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								clean_return :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_FREE ( & localdeps ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2011-10-10 14:16:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  char  * ast_module_name ( const  struct  ast_module  * mod )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! mod  | |  ! mod - > info )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  mod - > info - > name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								struct  loadupdate  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ( * updater ) ( void ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_ENTRY ( loadupdate )  entry ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  AST_DLLIST_HEAD_STATIC ( updaters ,  loadupdate ) ;  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_MUTEX_DEFINE_STATIC ( reloadlock ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Merged revisions 199022 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
  r199022 | seanbright | 2009-06-04 10:14:57 -0400 (Thu, 04 Jun 2009) | 40 lines
  
  Safely handle AMI connections/reload requests that occur during startup.
  
  During asterisk startup, a lock on the list of modules is obtained by the
  primary thread while each module is initialized.  Issue 13778 pointed out a
  problem with this approach, however.  Because the AMI is loaded before other
  modules, it is possible for a module reload to be issued by a connected client
  (via Action: Command), causing a deadlock.
  
  The resolution for 13778 was to move initialization of the manager to happen
  after the other modules had already been lodaded.  While this fixed this
  particular issue, it caused a problem for users (like FreePBX) who call AMI
  scripts via an #exec in a configuration file (See issue 15189).
  
  The solution I have come up with is to defer any reload requests that come in
  until after the server is fully booted.  When a call comes in to
  ast_module_reload (from wherever) before we are fully booted, the request is
  added to a queue of pending requests.  Once we are done booting up, we then
  execute these deferred requests in turn.
  
  Note that I have tried to make this a bit more intelligent in that it will not
  queue up more than 1 request for the same module to be reloaded, and if a
  general reload request comes in ('module reload') the queue is flushed and we
  only issue a single deferred reload for the entire system.
  
  As for how this will impact existing installations - Before 13778, a reload
  issued before module initialization was completed would result in a deadlock.
  After 13778, you simply couldn't connect to the manager during startup (which
  causes problems with #exec-that-calls-AMI configuration files).  I believe this
  is a good general purpose solution that won't negatively impact existing
  installations.
  
  (closes issue #15189)
  (closes issue #13778)
  Reported by: p_lindheimer
  Patches:
        06032009_15189_deferred_reloads.diff uploaded by seanbright (license 71)
  Tested by: p_lindheimer, seanbright
  
  Review: https://reviewboard.asterisk.org/r/272/
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@199051 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2009-06-04 14:31:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  reload_queue_item  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_ENTRY ( reload_queue_item )  entry ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  module [ 0 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  do_full_reload  =  0 ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  AST_DLLIST_HEAD_STATIC ( reload_queue ,  reload_queue_item ) ;  
						 
					
						
							
								
									
										
											 
										
											
												Merged revisions 199022 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
  r199022 | seanbright | 2009-06-04 10:14:57 -0400 (Thu, 04 Jun 2009) | 40 lines
  
  Safely handle AMI connections/reload requests that occur during startup.
  
  During asterisk startup, a lock on the list of modules is obtained by the
  primary thread while each module is initialized.  Issue 13778 pointed out a
  problem with this approach, however.  Because the AMI is loaded before other
  modules, it is possible for a module reload to be issued by a connected client
  (via Action: Command), causing a deadlock.
  
  The resolution for 13778 was to move initialization of the manager to happen
  after the other modules had already been lodaded.  While this fixed this
  particular issue, it caused a problem for users (like FreePBX) who call AMI
  scripts via an #exec in a configuration file (See issue 15189).
  
  The solution I have come up with is to defer any reload requests that come in
  until after the server is fully booted.  When a call comes in to
  ast_module_reload (from wherever) before we are fully booted, the request is
  added to a queue of pending requests.  Once we are done booting up, we then
  execute these deferred requests in turn.
  
  Note that I have tried to make this a bit more intelligent in that it will not
  queue up more than 1 request for the same module to be reloaded, and if a
  general reload request comes in ('module reload') the queue is flushed and we
  only issue a single deferred reload for the entire system.
  
  As for how this will impact existing installations - Before 13778, a reload
  issued before module initialization was completed would result in a deadlock.
  After 13778, you simply couldn't connect to the manager during startup (which
  causes problems with #exec-that-calls-AMI configuration files).  I believe this
  is a good general purpose solution that won't negatively impact existing
  installations.
  
  (closes issue #15189)
  (closes issue #13778)
  Reported by: p_lindheimer
  Patches:
        06032009_15189_deferred_reloads.diff uploaded by seanbright (license 71)
  Tested by: p_lindheimer, seanbright
  
  Review: https://reviewboard.asterisk.org/r/272/
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@199051 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2009-06-04 14:31:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 21:34:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  variable  is  set  by  load_dynamic_module  so  ast_module_register 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  can  know  what  pointer  is  being  registered . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  is  protected  by  the  module_list  lock . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-23 23:51:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  struct  ast_module  *  volatile  resource_being_loaded ;  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 21:34:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Used  by  AST_MODULE_INFO  to  register  with  the  module  loader . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  function  is  automatically  called  when  each  module  is  opened . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  It  must  never  be  used  from  outside  AST_MODULE_INFO . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								void  ast_module_register ( const  struct  ast_module_info  * info )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2017-11-21 21:34:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_module  * mod ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-29 23:00:52 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! loader_ready )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 22:11:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mod  =  ast_std_calloc ( 1 ,  sizeof ( * mod )  +  strlen ( info - > name )  +  1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-29 23:00:52 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! mod )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* We haven't even reached main() yet, if we can't
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  allocate  memory  at  this  point  just  give  up .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 22:11:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											fprintf ( stderr ,  " Allocation failure during startup. \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-29 23:00:52 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											exit ( 2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										strcpy ( mod - > resource ,  info - > name ) ;  /* safe */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mod - > info  =  info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mod - > flags . builtin  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_DLLIST_INSERT_TAIL ( & builtin_module_list ,  mod ,  entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* ast_module_register for built-in modules is run again during module preload. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 21:34:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  This  lock  protects  resource_being_loaded  as  well  as  the  module 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  list .   Normally  we  already  have  a  lock  on  module_list  when  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  begin  the  load  but  locking  again  from  here  prevents  corruption 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  if  an  asterisk  module  is  dlopen ' ed  from  outside  the  module  loader . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_LOCK ( & module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mod  =  resource_being_loaded ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! mod )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-05-28 22:54:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 5 ,  " Registering module %s \n " ,  info - > name ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												optional_api: Fix linking problems between modules that export global symbols
With the new work in Asterisk 12, there are some uses of the
optional_api that are prone to failure. The details are rather involved,
and captured on [the wiki][1].
This patch addresses the issue by removing almost all of the magic from
the optional API implementation. Instead of relying on weak symbol
resolution, a new optional_api.c module was added to Asterisk core.
For modules providing an optional API, the pointer to the implementation
function is registered with the core. For modules that use an optional
API, a pointer to a stub function, along with a optional_ref function
pointer are registered with the core. The optional_ref function pointers
is set to the implementation function when it's provided, or the stub
function when it's now.
Since the implementation no longer relies on magic, it is now supported
on all platforms. In the spirit of choice, an OPTIONAL_API flag was
added, so we can disable the optional_api if needed (maybe it's buggy on
some bizarre platform I haven't tested on)
The AST_OPTIONAL_API*() macros themselves remained unchanged, so
existing code could remain unchanged. But to help with debugging the
optional_api, the patch limits the #include of optional API's to just
the modules using the API. This also reduces resource waste maintaining
optional_ref pointers that aren't used.
Other changes made as a part of this patch:
 * The stubs for http_websocket that wrap system calls set errno to
   ENOSYS.
 * res_http_websocket now properly increments module use count.
 * In loader.c, the while() wrappers around dlclose() were removed. The
   while(!dlclose()) is actually an anti-pattern, which can lead to
   infinite loops if the module you're attempting to unload exports a
   symbol that was directly linked to.
 * The special handling of nonoptreq on systems without weak symbol
   support was removed, since we no longer rely on weak symbols for
   optional_api.
 [1]: https://wiki.asterisk.org/wiki/x/wACUAQ
(closes issue ASTERISK-22296)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/2797/
........
Merged revisions 397989 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@397990 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-30 13:40:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 21:34:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* This tells load_dynamic_module that we're registered. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									resource_being_loaded  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									mod - > info  =  info ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-04-17 03:16:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_opt_ref_debug )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-01 23:12:14 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mod - > ref_debug  =  ao2_t_alloc_options ( 0 ,  NULL ,  AO2_ALLOC_OPT_LOCK_NOLOCK ,  info - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-04-17 03:16:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									AST_LIST_HEAD_INIT ( & mod - > users ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_VECTOR_INIT ( & mod - > requires ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_INIT ( & mod - > optional_modules ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_INIT ( & mod - > enhances ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_INIT ( & mod - > reffed_deps ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-03-24 08:43:05 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_INSERT_TAIL ( & module_list ,  mod ,  entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* give the module a copy of its own handle, for later use in registrations and the like */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									* ( ( struct  ast_module  * * )  & ( info - > self ) )  =  mod ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-02 22:49:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(HAVE_PERMANENT_DLOPEN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( mod - > flags . builtin  ! =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  info_list_obj  * obj_tmp  =  ao2_find ( info_list ,  info - > name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! obj_tmp )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											obj_tmp  =  info_list_obj_alloc ( info - > name ,  info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( obj_tmp )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ao2_link ( info_list ,  obj_tmp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ao2_ref ( obj_tmp ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_ref ( obj_tmp ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-26 13:52:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  module_post_register ( struct  ast_module  * mod )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Split lists from mod->info. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res   =  ast_vector_string_split ( & mod - > requires ,  mod - > info - > requires ,  " , " ,  0 ,  strcasecmp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  | =  ast_vector_string_split ( & mod - > optional_modules ,  mod - > info - > optional_modules ,  " , " ,  0 ,  strcasecmp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  | =  ast_vector_string_split ( & mod - > enhances ,  mod - > info - > enhances ,  " , " ,  0 ,  strcasecmp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 21:34:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  module_destroy ( struct  ast_module  * mod )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_VECTOR_CALLBACK_VOID ( & mod - > requires ,  ast_free ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_FREE ( & mod - > requires ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_CALLBACK_VOID ( & mod - > optional_modules ,  ast_free ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_FREE ( & mod - > optional_modules ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_CALLBACK_VOID ( & mod - > enhances ,  ast_free ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_FREE ( & mod - > enhances ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Release references to all dependencies. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_CALLBACK_VOID ( & mod - > reffed_deps ,  ast_module_unref ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_FREE ( & mod - > reffed_deps ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 21:34:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_LIST_HEAD_DESTROY ( & mod - > users ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_cleanup ( mod - > ref_debug ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 22:11:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( mod - > flags . builtin )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_std_free ( mod ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_free ( mod ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 21:34:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								void  ast_module_unregister ( const  struct  ast_module_info  * info )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module  * mod  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* it is assumed that the users list in the module structure
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   will  already  be  empty ,  or  we  cannot  have  gotten  to  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   point 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									*/ 
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_LOCK ( & module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN ( & module_list ,  mod ,  entry )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  ( mod - > info  = =  info )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											AST_DLLIST_REMOVE_CURRENT ( entry ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( mod  & &  ! mod - > usecount )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  We  are  intentionally  leaking  mod  if  usecount  is  not  zero . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  This  is  necessary  if  the  module  is  being  forcefully  unloaded . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  In  addition  module_destroy  is  not  safe  to  run  after  exit ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  is  called .   ast_module_unregister  is  run  during  cleanup  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  the  process  when  libc  releases  each  module ' s  shared  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  library . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
									
										
										
										
											2014-05-28 22:54:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_debug ( 5 ,  " Unregistering module %s \n " ,  info - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 21:34:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										module_destroy ( mod ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-11-05 21:42:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_module_user  * __ast_module_user_add ( struct  ast_module  * mod ,  struct  ast_channel  * chan )  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2012-11-05 21:42:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_module_user  * u ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-11-05 21:42:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									u  =  ast_calloc ( 1 ,  sizeof ( * u ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! u )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-11-05 21:42:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u - > chan  =  chan ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_LOCK ( & mod - > users ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_INSERT_HEAD ( & mod - > users ,  u ,  entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_UNLOCK ( & mod - > users ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-04-17 03:16:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( mod - > ref_debug )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( mod - > ref_debug ,  + 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-11 17:03:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ast_atomic_fetchadd_int ( & mod - > usecount ,  + 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_update_use_count ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  __ast_module_user_remove ( struct  ast_module  * mod ,  struct  ast_module_user  * u )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2012-11-05 21:42:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2012-12-17 23:10:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									AST_LIST_LOCK ( & mod - > users ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-12-17 23:10:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									u  =  AST_LIST_REMOVE ( & mod - > users ,  u ,  entry ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									AST_LIST_UNLOCK ( & mod - > users ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-12-17 23:10:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Was  not  in  the  list .   Either  a  bad  pointer  or 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  __ast_module_user_hangup_all ( )  has  been  called . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-04-17 03:16:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( mod - > ref_debug )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( mod - > ref_debug ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-11 17:03:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ast_atomic_fetchadd_int ( & mod - > usecount ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-06 21:20:11 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_free ( u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_update_use_count ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  __ast_module_user_hangup_all ( struct  ast_module  * mod )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module_user  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_LOCK ( & mod - > users ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ( u  =  AST_LIST_REMOVE_HEAD ( & mod - > users ,  entry ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2012-02-22 21:22:43 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( u - > chan )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_softhangup ( u - > chan ,  AST_SOFTHANGUP_APPUNLOAD ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-11 17:03:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-04-17 03:16:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( mod - > ref_debug )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_ref ( mod - > ref_debug ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-11 17:03:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										ast_atomic_fetchadd_int ( & mod - > usecount ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-06 21:20:11 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_free ( u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_UNLOCK ( & mod - > users ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-03-04 23:04:29 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_update_use_count ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  printdigest ( const  unsigned  char  * d )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  x ,  pos ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  buf [ 256 ] ;  /* large enough so we don't have to worry */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( pos  =  0 ,  x  =  0 ;  x  <  16 ;  x + + ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-17 10:23:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pos  + =  sprintf ( buf  +  pos ,  "  %02hhx " ,  * d + + ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-06-24 18:51:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Unexpected signature:%s \n " ,  buf ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-03-23 11:08:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# define key_matches(a, b) (memcmp((a), (b), 16) == 0) 
  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  verify_key ( const  unsigned  char  * key )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  MD5Context  c ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  char  digest [ 16 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MD5Init ( & c ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MD5Update ( & c ,  key ,  strlen ( ( char  * ) key ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MD5Final ( digest ,  & c ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( key_matches ( expected_key ,  digest ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									printdigest ( digest ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  size_t  resource_name_baselen ( const  char  * name )  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									size_t  len  =  strlen ( name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( len  >  3  & &  ! strcasecmp ( name  +  len  -  3 ,  " .so " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  len  -  3 ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  resource_name_match ( const  char  * name1 ,  size_t  baselen1 ,  const  char  * name2 )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( baselen1  ! =  resource_name_baselen ( name2 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  strncasecmp ( name1 ,  name2 ,  baselen1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ast_module  * find_resource ( const  char  * resource ,  int  do_lock )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module  * cur ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									size_t  resource_baselen  =  resource_name_baselen ( resource ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( do_lock )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_DLLIST_LOCK ( & module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_TRAVERSE ( & module_list ,  cur ,  entry )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! resource_name_match ( resource ,  resource_baselen ,  cur - > resource ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( do_lock )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cur ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												optional_api: Fix linking problems between modules that export global symbols
With the new work in Asterisk 12, there are some uses of the
optional_api that are prone to failure. The details are rather involved,
and captured on [the wiki][1].
This patch addresses the issue by removing almost all of the magic from
the optional API implementation. Instead of relying on weak symbol
resolution, a new optional_api.c module was added to Asterisk core.
For modules providing an optional API, the pointer to the implementation
function is registered with the core. For modules that use an optional
API, a pointer to a stub function, along with a optional_ref function
pointer are registered with the core. The optional_ref function pointers
is set to the implementation function when it's provided, or the stub
function when it's now.
Since the implementation no longer relies on magic, it is now supported
on all platforms. In the spirit of choice, an OPTIONAL_API flag was
added, so we can disable the optional_api if needed (maybe it's buggy on
some bizarre platform I haven't tested on)
The AST_OPTIONAL_API*() macros themselves remained unchanged, so
existing code could remain unchanged. But to help with debugging the
optional_api, the patch limits the #include of optional API's to just
the modules using the API. This also reduces resource waste maintaining
optional_ref pointers that aren't used.
Other changes made as a part of this patch:
 * The stubs for http_websocket that wrap system calls set errno to
   ENOSYS.
 * res_http_websocket now properly increments module use count.
 * In loader.c, the while() wrappers around dlclose() were removed. The
   while(!dlclose()) is actually an anti-pattern, which can lead to
   infinite loops if the module you're attempting to unload exports a
   symbol that was directly linked to.
 * The special handling of nonoptreq on systems without weak symbol
   support was removed, since we no longer rely on weak symbols for
   optional_api.
 [1]: https://wiki.asterisk.org/wiki/x/wACUAQ
(closes issue ASTERISK-22296)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/2797/
........
Merged revisions 397989 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@397990 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-30 13:40:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  dlclose ( ) ,  with  failure  logging . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  logged_dlclose ( const  char  * name ,  void  * lib )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												core/loader: Don't call dlclose in a while loop
For awhile now, we've noticed continuous integration builds hanging on CentOS 6
64-bit build agents. After resolving a number of problems with symbols, strange
locks, and other shenanigans, the problem has persisted. In all cases, gdb
shows the Asterisk process stuck in loader.c on one of the infinite while loops
that calls dlclose repeatedly until success.
The documentation of dlclose states that it returns 0 on success; any other
value on error. It does not state that repeatedly calling it will eventually
clear those errors. Most likely, the repeated calls to dlclose was to force a
close by exhausting the references on the library; however, that will never
succeed if:
(a) There is some fundamental error at work in the loaded library that
    precludes unloading it
(b) Some other loaded module is referencing a symbol in the currently loaded
    module
This results in Asterisk sitting forever.
Since we have matching pairs of dlopen/dlclose, this patch opts to only call
dlclose once, and log out as an ERROR if dlclose fails to return success. If
nothing else, this might help to determine why on the CentOS 6 64-bit build agent
things are not closing successfully.
Review: https://reviewboard.asterisk.org/r/2970
........
Merged revisions 402287 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 402288 from http://svn.asterisk.org/svn/asterisk/branches/11
........
Merged revisions 402289 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@402290 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-10-31 16:06:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									char  * error ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! lib )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Clear any existing error */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dlerror ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( dlclose ( lib ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										error  =  dlerror ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( AST_LOG_ERROR ,  " Failure in dlclose for module '%s': %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											S_OR ( name ,  " unknown " ) ,  S_OR ( error ,  " Unknown error " ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-02 22:49:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# if defined(HAVE_PERMANENT_DLOPEN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										manual_mod_unreg ( name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
											 
										
											
												optional_api: Fix linking problems between modules that export global symbols
With the new work in Asterisk 12, there are some uses of the
optional_api that are prone to failure. The details are rather involved,
and captured on [the wiki][1].
This patch addresses the issue by removing almost all of the magic from
the optional API implementation. Instead of relying on weak symbol
resolution, a new optional_api.c module was added to Asterisk core.
For modules providing an optional API, the pointer to the implementation
function is registered with the core. For modules that use an optional
API, a pointer to a stub function, along with a optional_ref function
pointer are registered with the core. The optional_ref function pointers
is set to the implementation function when it's provided, or the stub
function when it's now.
Since the implementation no longer relies on magic, it is now supported
on all platforms. In the spirit of choice, an OPTIONAL_API flag was
added, so we can disable the optional_api if needed (maybe it's buggy on
some bizarre platform I haven't tested on)
The AST_OPTIONAL_API*() macros themselves remained unchanged, so
existing code could remain unchanged. But to help with debugging the
optional_api, the patch limits the #include of optional API's to just
the modules using the API. This also reduces resource waste maintaining
optional_ref pointers that aren't used.
Other changes made as a part of this patch:
 * The stubs for http_websocket that wrap system calls set errno to
   ENOSYS.
 * res_http_websocket now properly increments module use count.
 * In loader.c, the while() wrappers around dlclose() were removed. The
   while(!dlclose()) is actually an anti-pattern, which can lead to
   infinite loops if the module you're attempting to unload exports a
   symbol that was directly linked to.
 * The special handling of nonoptreq on systems without weak symbol
   support was removed, since we no longer rely on weak symbols for
   optional_api.
 [1]: https://wiki.asterisk.org/wiki/x/wACUAQ
(closes issue ASTERISK-22296)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/2797/
........
Merged revisions 397989 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@397990 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-30 13:40:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(HAVE_RTLD_NOLOAD) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Check  to  see  if  the  given  resource  is  loaded . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  resource_name  Name  of  the  resource ,  including  . so  suffix . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ return  False  ( 0 )  if  module  is  not  loaded . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ return  True  ( non - zero )  if  module  is  loaded . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  is_module_loaded ( const  char  * resource_name )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  fn [ PATH_MAX ]  =  " " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * lib ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									snprintf ( fn ,  sizeof ( fn ) ,  " %s/%s " ,  ast_config_AST_MODULE_DIR , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										resource_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									lib  =  dlopen ( fn ,  RTLD_LAZY  |  RTLD_NOLOAD ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( lib )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										logged_dlclose ( resource_name ,  lib ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								static  void  unload_dynamic_module ( struct  ast_module  * mod )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2015-03-22 23:11:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# if defined(HAVE_RTLD_NOLOAD) 
  
						 
					
						
							
								
									
										
											 
										
											
												optional_api: Fix linking problems between modules that export global symbols
With the new work in Asterisk 12, there are some uses of the
optional_api that are prone to failure. The details are rather involved,
and captured on [the wiki][1].
This patch addresses the issue by removing almost all of the magic from
the optional API implementation. Instead of relying on weak symbol
resolution, a new optional_api.c module was added to Asterisk core.
For modules providing an optional API, the pointer to the implementation
function is registered with the core. For modules that use an optional
API, a pointer to a stub function, along with a optional_ref function
pointer are registered with the core. The optional_ref function pointers
is set to the implementation function when it's provided, or the stub
function when it's now.
Since the implementation no longer relies on magic, it is now supported
on all platforms. In the spirit of choice, an OPTIONAL_API flag was
added, so we can disable the optional_api if needed (maybe it's buggy on
some bizarre platform I haven't tested on)
The AST_OPTIONAL_API*() macros themselves remained unchanged, so
existing code could remain unchanged. But to help with debugging the
optional_api, the patch limits the #include of optional API's to just
the modules using the API. This also reduces resource waste maintaining
optional_ref pointers that aren't used.
Other changes made as a part of this patch:
 * The stubs for http_websocket that wrap system calls set errno to
   ENOSYS.
 * res_http_websocket now properly increments module use count.
 * In loader.c, the while() wrappers around dlclose() were removed. The
   while(!dlclose()) is actually an anti-pattern, which can lead to
   infinite loops if the module you're attempting to unload exports a
   symbol that was directly linked to.
 * The special handling of nonoptreq on systems without weak symbol
   support was removed, since we no longer rely on weak symbols for
   optional_api.
 [1]: https://wiki.asterisk.org/wiki/x/wACUAQ
(closes issue ASTERISK-22296)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/2797/
........
Merged revisions 397989 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@397990 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-30 13:40:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									char  * name  =  ast_strdupa ( ast_module_name ( mod ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-03-22 23:11:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2006-08-26 19:45:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									void  * lib  =  mod - > lib ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* WARNING: the structure pointed to by mod is going to
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   disappear  when  this  operation  succeeds ,  so  we  can ' t 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   dereference  it  */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												core/loader: Don't call dlclose in a while loop
For awhile now, we've noticed continuous integration builds hanging on CentOS 6
64-bit build agents. After resolving a number of problems with symbols, strange
locks, and other shenanigans, the problem has persisted. In all cases, gdb
shows the Asterisk process stuck in loader.c on one of the infinite while loops
that calls dlclose repeatedly until success.
The documentation of dlclose states that it returns 0 on success; any other
value on error. It does not state that repeatedly calling it will eventually
clear those errors. Most likely, the repeated calls to dlclose was to force a
close by exhausting the references on the library; however, that will never
succeed if:
(a) There is some fundamental error at work in the loaded library that
    precludes unloading it
(b) Some other loaded module is referencing a symbol in the currently loaded
    module
This results in Asterisk sitting forever.
Since we have matching pairs of dlopen/dlclose, this patch opts to only call
dlclose once, and log out as an ERROR if dlclose fails to return success. If
nothing else, this might help to determine why on the CentOS 6 64-bit build agent
things are not closing successfully.
Review: https://reviewboard.asterisk.org/r/2970
........
Merged revisions 402287 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 402288 from http://svn.asterisk.org/svn/asterisk/branches/11
........
Merged revisions 402289 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@402290 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-10-31 16:06:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									logged_dlclose ( ast_module_name ( mod ) ,  lib ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												optional_api: Fix linking problems between modules that export global symbols
With the new work in Asterisk 12, there are some uses of the
optional_api that are prone to failure. The details are rather involved,
and captured on [the wiki][1].
This patch addresses the issue by removing almost all of the magic from
the optional API implementation. Instead of relying on weak symbol
resolution, a new optional_api.c module was added to Asterisk core.
For modules providing an optional API, the pointer to the implementation
function is registered with the core. For modules that use an optional
API, a pointer to a stub function, along with a optional_ref function
pointer are registered with the core. The optional_ref function pointers
is set to the implementation function when it's provided, or the stub
function when it's now.
Since the implementation no longer relies on magic, it is now supported
on all platforms. In the spirit of choice, an OPTIONAL_API flag was
added, so we can disable the optional_api if needed (maybe it's buggy on
some bizarre platform I haven't tested on)
The AST_OPTIONAL_API*() macros themselves remained unchanged, so
existing code could remain unchanged. But to help with debugging the
optional_api, the patch limits the #include of optional API's to just
the modules using the API. This also reduces resource waste maintaining
optional_ref pointers that aren't used.
Other changes made as a part of this patch:
 * The stubs for http_websocket that wrap system calls set errno to
   ENOSYS.
 * res_http_websocket now properly increments module use count.
 * In loader.c, the while() wrappers around dlclose() were removed. The
   while(!dlclose()) is actually an anti-pattern, which can lead to
   infinite loops if the module you're attempting to unload exports a
   symbol that was directly linked to.
 * The special handling of nonoptreq on systems without weak symbol
   support was removed, since we no longer rely on weak symbols for
   optional_api.
 [1]: https://wiki.asterisk.org/wiki/x/wACUAQ
(closes issue ASTERISK-22296)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/2797/
........
Merged revisions 397989 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@397990 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-30 13:40:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* There are several situations where the module might still be resident
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  in  memory . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  If  somehow  there  was  another  dlopen ( )  on  the  same  module  ( unlikely , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  since  that  all  is  supposed  to  happen  in  loader . c ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Avoid  the  temptation  of  repeating  the  dlclose ( ) .  The  other  code  that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  dlopened  the  module  still  has  its  module  reference ,  and  should  close 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  it  itself .  In  other  situations ,  dlclose ( )  will  happily  return  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  for  as  many  times  as  you  wish  to  call  it . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(HAVE_RTLD_NOLOAD) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_module_loaded ( name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_WARNING ,  " Module '%s' could not be completely unloaded \n " ,  name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  load_dlopen_missing ( struct  ast_str  * * list ,  struct  ast_vector_string  * deps )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  c  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  AST_VECTOR_SIZE ( deps ) ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  char  * dep  =  AST_VECTOR_GET ( deps ,  i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! find_resource ( dep ,  0 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											STR_APPEND_TEXT ( dep ,  list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											c + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  c ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 00:10:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Attempt  to  dlopen  a  module . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  resource_in  The  module  name  to  load . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  so_ext  " .so "  or  blank  if  " .so "  is  already  part  of  resource_in . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  filename  Passed  directly  to  dlopen . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  flags  Passed  directly  to  dlopen . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  suppress_logging  Do  not  log  any  error  from  dlopen . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ return  Pointer  to  opened  module ,  NULL  on  error . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ warning  module_list  must  be  locked  before  calling  this  function . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ast_module  * load_dlopen ( const  char  * resource_in ,  const  char  * so_ext ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * filename ,  int  flags ,  unsigned  int  suppress_logging ) 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module  * mod ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 21:34:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_assert ( ! resource_being_loaded ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 00:10:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									mod  =  ast_calloc ( 1 ,  sizeof ( * mod )  +  strlen ( resource_in )  +  strlen ( so_ext )  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! mod )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 00:10:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									sprintf ( mod - > resource ,  " %s%s " ,  resource_in ,  so_ext ) ;  /* safe */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 14:42:03 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 00:10:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									resource_being_loaded  =  mod ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mod - > lib  =  dlopen ( filename ,  flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-02 22:49:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# if defined(HAVE_PERMANENT_DLOPEN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									manual_mod_reg ( mod - > lib ,  mod - > resource ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2017-11-21 21:34:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( resource_being_loaded )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  ast_str  * list ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  c  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-29 07:31:56 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										const  char  * dlerror_msg  =  ast_strdupa ( S_OR ( dlerror ( ) ,  " " ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 21:34:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										resource_being_loaded  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 00:10:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( mod - > lib )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											module_load_error ( " Module '%s' did not register itself during load \n " ,  resource_in ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 00:10:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											logged_dlclose ( resource_in ,  mod - > lib ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  error_return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( suppress_logging )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  error_return ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-23 14:50:57 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										resource_being_loaded  =  mod ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mod - > lib  =  dlopen ( filename ,  RTLD_LAZY  |  RTLD_LOCAL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-02 22:49:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# if defined(HAVE_PERMANENT_DLOPEN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										manual_mod_reg ( mod - > lib ,  mod - > resource ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( resource_being_loaded )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											resource_being_loaded  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											module_load_error ( " Error loading module '%s': %s \n " ,  resource_in ,  dlerror_msg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											logged_dlclose ( resource_in ,  mod - > lib ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  error_return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										list  =  ast_str_create ( 64 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( list )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( module_post_register ( mod ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												goto  loaded_error ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											c  =  load_dlopen_missing ( & list ,  & mod - > requires ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											c  + =  load_dlopen_missing ( & list ,  & mod - > enhances ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifndef OPTIONAL_API 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											c  + =  load_dlopen_missing ( & list ,  & mod - > optional_modules ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( list  & &  ast_str_strlen ( list ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											module_load_error ( " Error loading module '%s', missing %s: %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												resource_in ,  c  = =  1  ?  " dependency "  :  " dependencies " ,  ast_str_buffer ( list ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											module_load_error ( " Error loading module '%s': %s \n " ,  resource_in ,  dlerror_msg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								loaded_error :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_free ( list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unload_dynamic_module ( mod ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								error_return :  
						 
					
						
							
								
									
										
										
										
											2017-11-21 21:34:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_free ( mod ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 00:10:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 00:10:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  mod ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2006-08-21 14:42:03 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 00:30:43 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  struct  ast_module  * load_dynamic_module ( const  char  * resource_in ,  unsigned  int  suppress_logging )  
						 
					
						
							
								
									
										
										
										
											2017-11-21 00:10:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  fn [ PATH_MAX ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module  * mod ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									size_t  resource_in_len  =  strlen ( resource_in ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * so_ext  =  " " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( resource_in_len  <  4  | |  strcasecmp ( resource_in  +  resource_in_len  -  3 ,  " .so " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										so_ext  =  " .so " ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-23 19:28:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 00:10:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									snprintf ( fn ,  sizeof ( fn ) ,  " %s/%s%s " ,  ast_config_AST_MODULE_DIR ,  resource_in ,  so_ext ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 00:30:43 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Try loading in quiet mode first with RTLD_LOCAL.  The majority of modules do not
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  export  symbols  so  this  allows  the  least  number  of  calls  to  dlopen .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mod  =  load_dlopen ( resource_in ,  so_ext ,  fn ,  RTLD_NOW  |  RTLD_LOCAL ,  suppress_logging ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 14:42:03 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 00:30:43 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! mod  | |  ! ast_test_flag ( mod - > info ,  AST_MODFLAG_GLOBAL_SYMBOLS ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 00:10:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  mod ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-23 19:28:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 00:10:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Close the module so we can reopen with correct flags. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									logged_dlclose ( resource_in ,  mod - > lib ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 14:42:03 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 00:30:43 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  load_dlopen ( resource_in ,  so_ext ,  fn ,  RTLD_NOW  |  RTLD_GLOBAL ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
											 
										
											
												optional_api: Fix linking problems between modules that export global symbols
With the new work in Asterisk 12, there are some uses of the
optional_api that are prone to failure. The details are rather involved,
and captured on [the wiki][1].
This patch addresses the issue by removing almost all of the magic from
the optional API implementation. Instead of relying on weak symbol
resolution, a new optional_api.c module was added to Asterisk core.
For modules providing an optional API, the pointer to the implementation
function is registered with the core. For modules that use an optional
API, a pointer to a stub function, along with a optional_ref function
pointer are registered with the core. The optional_ref function pointers
is set to the implementation function when it's provided, or the stub
function when it's now.
Since the implementation no longer relies on magic, it is now supported
on all platforms. In the spirit of choice, an OPTIONAL_API flag was
added, so we can disable the optional_api if needed (maybe it's buggy on
some bizarre platform I haven't tested on)
The AST_OPTIONAL_API*() macros themselves remained unchanged, so
existing code could remain unchanged. But to help with debugging the
optional_api, the patch limits the #include of optional API's to just
the modules using the API. This also reduces resource waste maintaining
optional_ref pointers that aren't used.
Other changes made as a part of this patch:
 * The stubs for http_websocket that wrap system calls set errno to
   ENOSYS.
 * res_http_websocket now properly increments module use count.
 * In loader.c, the while() wrappers around dlclose() were removed. The
   while(!dlclose()) is actually an anti-pattern, which can lead to
   infinite loops if the module you're attempting to unload exports a
   symbol that was directly linked to.
 * The special handling of nonoptreq on systems without weak symbol
   support was removed, since we no longer rely on weak symbols for
   optional_api.
 [1]: https://wiki.asterisk.org/wiki/x/wACUAQ
(closes issue ASTERISK-22296)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/2797/
........
Merged revisions 397989 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@397990 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-30 13:40:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-27 22:49:43 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  modules_shutdown ( void )  
						 
					
						
							
								
									
										
										
										
											2007-06-05 15:54:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module  * mod ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-17 01:28:57 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  somethingchanged ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-05 15:54:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_LOCK ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-05 15:54:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-11-09 07:37:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*!\note Some resources, like timers, are started up dynamically, and thus
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  may  be  still  in  use ,  even  if  all  channels  are  dead .   We  must  therefore 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  check  the  usecount  before  asking  modules  to  unload .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									do  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Reset flag before traversing the list */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										somethingchanged  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN ( & module_list ,  mod ,  entry )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-17 01:28:57 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( mod - > usecount )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												ast_debug ( 1 ,  " Passing on %s: its use count is %d \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													mod - > resource ,  mod - > usecount ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-09 07:37:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											AST_DLLIST_REMOVE_CURRENT ( entry ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-07-09 17:50:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( mod - > flags . running  & &  ! mod - > flags . declined  & &  mod - > info - > unload )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 10:46:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												ast_verb ( 4 ,  " Unloading %s \n " ,  mod - > resource ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-09 07:37:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												mod - > info - > unload ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 21:34:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											module_destroy ( mod ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-09 07:37:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											somethingchanged  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-11 17:03:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! somethingchanged )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_DLLIST_TRAVERSE ( & module_list ,  mod ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( mod - > flags . keepuntilshutdown )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ast_module_unref ( mod ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													mod - > flags . keepuntilshutdown  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													somethingchanged  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-17 01:28:57 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  while  ( somethingchanged ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-09 07:37:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-17 01:28:57 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									res  =  AST_DLLIST_EMPTY ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-27 22:49:43 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-17 01:28:57 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  ! res ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-05 15:54:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-02 18:07:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Whether  or  not  this  module  should  be  able  to  be  unloaded  successfully , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *         if  we  recursively  unload  any  modules  that  are  dependent  on  it . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  module_list  should  be  locked  when  calling  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  if  not ,  1  if  likely  possible 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  graceful_unload_possible ( struct  ast_module  * target ,  struct  ast_vector_const_string  * dependents )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module  * mod ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  usecount  =  target - > usecount ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Check the reffed_deps of each module to see if we're one of them. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_TRAVERSE ( & module_list ,  mod ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( AST_VECTOR_GET_CMP ( & mod - > reffed_deps ,  target ,  AST_VECTOR_ELEM_DEFAULT_CMP ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											const  char  * name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* This module is dependent on the target.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  If  we  can  unload  this  module  gracefully , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  then  that  would  decrement  our  use  count . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  If  any  single  module  could  not  be  unloaded  gracefully , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  then  we  don ' t  proceed .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											int  unloadable ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( AST_VECTOR_GET_CMP ( dependents ,  ast_module_name ( mod ) ,  ! strcasecmp ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* Already in our list, we already checked this module,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 *  and  we  gave  it  the  green  light .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_debug ( 3 ,  " Skipping duplicate dependent %s \n " ,  ast_module_name ( mod ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( ! - - usecount )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											unloadable  =  graceful_unload_possible ( mod ,  dependents ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! unloadable )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_log ( LOG_NOTICE ,  " Can't unload %s right now because %s is dependent on it \n " ,  ast_module_name ( target ) ,  ast_module_name ( mod ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Insert at beginning, so later if we're loading modules again automatically, we can do so in the same order. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											name  =  ast_strdup ( ast_module_name ( mod ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_debug ( 3 ,  " Found new dependent %s \n " ,  ast_module_name ( mod ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( AST_VECTOR_INSERT_AT ( dependents ,  0 ,  name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_log ( LOG_ERROR ,  " Failed to add module '%s' to vector \n " ,  ast_module_name ( mod ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! - - usecount )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( usecount )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_NOTICE ,  " Module %s cannot be unloaded (would still have use count %d/%d after unloading dependents) \n " ,  ast_module_name ( target ) ,  usecount ,  target - > usecount ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Unload  a  resource 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  resource_name  Module  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  force 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  recursive  Whether  to  attempt  to  recursively  unload  dependents  of  this  module  and  load  them  again  afterwards 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  dependents .  Can  be  NULL  if  autounload  is  0. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  on  success ,  - 1  on  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  auto_unload_resource ( const  char  * resource_name ,  enum  ast_module_unload_mode  force ,  int  recursive ,  struct  ast_vector_const_string  * dependents )  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module  * mod ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  error  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_LOCK ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-22 23:06:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ( mod  =  find_resource ( resource_name ,  0 ) ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-02-19 21:54:09 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_log ( LOG_WARNING ,  " Unload failed, '%s' could not be found \n " ,  resource_name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-05-12 19:59:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-22 23:06:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-07-09 18:24:03 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! mod - > flags . running  | |  mod - > flags . declined )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 21:44:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* If the user asks to unload a module that didn't load, obey.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Otherwise ,  we  never  dlclose ( )  modules  that  fail  to  load , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  which  means  if  the  module  ( shared  object )  is  updated , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  we  can ' t  load  the  updated  module  since  we  never  dlclose ( ) ' d  it . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Accordingly ,  obey  the  unload  request  so  we  can  load  the  module 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  from  scratch  next  time . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_NOTICE ,  " Unloading module '%s' that previously declined to load \n " ,  resource_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										error  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  exit ;  /* Skip all the intervening !error checks, only the last one is relevant. */ 
							 
						 
					
						
							
								
									
										
										
										
											2010-07-09 18:24:03 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-02 18:07:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! error  & &  mod - > usecount  >  0  & &  recursive )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Try automatically unloading all modules dependent on the module we're trying to unload,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  and  then ,  optionally ,  load  them  back  again  if  we  end  up  loading  this  module  again . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  If  any  modules  that  have  us  as  a  dependency  can ' t  be  unloaded ,  for  whatever  reason , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  then  the  entire  unload  operation  will  fail ,  so  to  try  to  make  this  an  atomic  operation 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  and  avoid  leaving  modules  in  a  partial  unload  state ,  first  check  if  we  think  we ' re  going 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  to  be  able  to  pull  this  off ,  and  if  not ,  abort . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  A  race  condition  is  technically  still  possible ,  if  some  depending  module  suddenly  goes  in  use 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  between  this  check  and  trying  to  unload  it ,  but  this  takes  care  of  the  majority  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  easy - to - avoid  cases  that  would  fail  eventually  anyways . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Note  that  we  can  encounter  false  negatives  ( e . g .  unloading  all  the  dependents  would  allow 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  a  module  to  unload ,  but  graceful_unload_possible  returns  0 ) .  This  is  because  it ' s  only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  checking  direct  module  dependencies ;  other  dependencies  caused  by  a  module  registering 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  a  resource  that  cause  its  ref  count  to  get  bumped  aren ' t  accounted  for  here . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( graceful_unload_possible ( mod ,  dependents ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											int  i ,  res  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											size_t  num_deps  =  AST_VECTOR_SIZE ( dependents ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_debug ( 1 ,  " %lu module%s will need to be unloaded \n " ,  AST_VECTOR_SIZE ( dependents ) ,  ESS ( AST_VECTOR_SIZE ( dependents ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Unload from the end, since the last module was the first one added, which means it isn't a dependency of anything else. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  ( i  =  AST_VECTOR_SIZE ( dependents )  -  1 ;  i  > =  0 ;  i - - )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												const  char  * depname  =  AST_VECTOR_GET ( dependents ,  i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												res  =  ast_unload_resource ( depname ,  force ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ast_log ( LOG_WARNING ,  " Failed to unload %lu module%s automatically (%s could not be unloaded) \n " ,  num_deps ,  ESS ( num_deps ) ,  depname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													/* To be polite, load modules that we already unloaded,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 *  to  try  to  leave  things  the  way  they  were  when  we  started .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													for  ( i + + ;  i  <  num_deps ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														const  char  * depname  =  AST_VECTOR_GET ( dependents ,  i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														res  =  ast_load_resource ( depname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															ast_log ( LOG_WARNING ,  " Could not load module '%s' again automatically \n " ,  depname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Either we failed, or we successfully unloaded everything.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  If  we  succeeded ,  we  can  now  proceed  and  unload  ourselves .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ( ! error  & &  ( mod - > usecount  >  0 ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-02 18:07:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( force )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_WARNING ,  " Warning:  Forcing removal of module '%s' with use count %d \n " ,  resource_name ,  mod - > usecount ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_WARNING ,  " %s unload failed, '%s' has use count %d \n " ,  recursive  ?  " Recursive soft "  :  " Soft " ,  resource_name ,  mod - > usecount ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											error  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2012-12-17 23:10:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Request any channels attached to the module to hangup. */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										__ast_module_user_hangup_all ( mod ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 10:46:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_verb ( 4 ,  " Unloading %s \n " ,  mod - > resource ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-12-17 23:10:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  mod - > info - > unload ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_WARNING ,  " Firm unload failed for %s \n " ,  resource_name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-12-17 23:10:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( force  < =  AST_FORCE_FIRM )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												error  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-12-17 23:10:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												ast_log ( LOG_WARNING ,  " ** Dangerous **: Unloading resource anyway, at user request \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-12-17 23:10:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  Request  hangup  on  any  channels  that  managed  to  get  attached 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  while  we  called  the  module  unload  function . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											__ast_module_user_hangup_all ( mod ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											sched_yield ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! error ) 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-03 16:43:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mod - > flags . running  =  mod - > flags . declined  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 21:44:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								exit :  
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-08-13 20:36:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										unload_dynamic_module ( mod ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-08-13 20:36:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_test_suite_event_notify ( " MODULE_UNLOAD " ,  " Message: %s " ,  resource_name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										ast_update_use_count ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-06 21:27:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										publish_unload_message ( resource_name ,  " Success " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-24 08:43:05 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-02 18:07:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_refresh_resource ( const  char  * resource_name ,  enum  ast_module_unload_mode  force ,  int  recursive )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( recursive )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Recursively unload dependents of this module and then load them back again */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  res ,  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_vector_const_string  dependents ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_VECTOR_INIT ( & dependents ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  auto_unload_resource ( resource_name ,  force ,  recursive ,  & dependents ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_VECTOR_FREE ( & dependents ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Start by loading the target again. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_load_resource ( resource_name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_WARNING ,  " Failed to load module '%s' again automatically \n " ,  resource_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_VECTOR_FREE ( & dependents ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Finally, load again any modules we had to unload in order to refresh the target.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  We  must  load  modules  in  the  reverse  order  that  we  unloaded  them , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  to  preserve  dependency  requirements .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  ( i  =  0 ;  i  <  AST_VECTOR_SIZE ( & dependents ) ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											const  char  * depname  =  AST_VECTOR_GET ( & dependents ,  i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											int  mres  =  ast_load_resource ( depname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( mres )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_log ( LOG_WARNING ,  " Could not load module '%s' again automatically \n " ,  depname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											res  | =  mres ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_VECTOR_FREE ( & dependents ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  res  ?  - 1  :  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Simple case: just unload and load the module again */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_unload_resource ( resource_name ,  force ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ast_load_resource ( resource_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_unload_resource ( const  char  * resource_name ,  enum  ast_module_unload_mode  force )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  auto_unload_resource ( resource_name ,  force ,  0 ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-30 18:30:18 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  module_matches_helper_type ( struct  ast_module  * mod ,  enum  ast_module_helper_type  type )  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2017-10-30 18:30:18 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_MODULE_HELPER_UNLOAD : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ! mod - > usecount  & &  mod - > flags . running  & &  ! mod - > flags . declined ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-30 18:30:18 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_MODULE_HELPER_RELOAD : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  mod - > flags . running  & &  mod - > info - > reload ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_MODULE_HELPER_RUNNING : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  mod - > flags . running ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_MODULE_HELPER_LOADED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* if we have a 'struct ast_module' then we're loaded. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* This function is not called for AST_MODULE_HELPER_LOAD. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Unknown ast_module_helper_type. Assume it doesn't match. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-30 01:32:32 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-30 18:30:18 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-25 13:06:12 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  module_load_word  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * word ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									size_t  len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									size_t  moddir_len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  module_load_helper_on_file ( const  char  * dir_name ,  const  char  * filename ,  void  * obj )  
						 
					
						
							
								
									
										
										
										
											2017-10-30 18:30:18 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2018-01-25 13:06:12 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  module_load_word  * word  =  obj ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-30 18:30:18 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_module  * mod ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-25 13:06:12 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									char  * filename_merged  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-30 18:30:18 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-25 13:06:12 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* dir_name will never be shorter than word->moddir_len. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dir_name  + =  word - > moddir_len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ast_strlen_zero ( dir_name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_assert ( dir_name [ 0 ]  = =  ' / ' ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-25 13:06:12 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										dir_name  + =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_asprintf ( & filename_merged ,  " %s/%s " ,  dir_name ,  filename )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* If we can't allocate the string just give up! */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-25 13:06:12 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										filename  =  filename_merged ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-30 18:30:18 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-25 13:06:12 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! strncasecmp ( filename ,  word - > word ,  word - > len ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Don't list files that are already loaded! */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mod  =  find_resource ( filename ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! mod  | |  ! mod - > flags . running )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_cli_completion_add ( ast_strdup ( filename ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-30 18:30:18 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-25 13:06:12 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_free ( filename_merged ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-30 18:30:18 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-25 13:06:12 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2017-10-30 18:30:18 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-25 13:06:12 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  module_load_helper ( const  char  * word )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  module_load_word  word_l  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. word  =  word , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. len  =  strlen ( word ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. moddir_len  =  strlen ( ast_config_AST_MODULE_DIR ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-30 18:30:18 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-25 13:06:12 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_LOCK ( & module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_file_read_dirs ( ast_config_AST_MODULE_DIR ,  module_load_helper_on_file ,  & word_l ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-30 18:30:18 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								char  * ast_module_helper ( const  char  * line ,  const  char  * word ,  int  pos ,  int  state ,  int  rpos ,  enum  ast_module_helper_type  type )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module  * mod ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  which  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  wordlen  =  strlen ( word ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * ret  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( pos  ! =  rpos )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-03 12:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Tab completion can't be used during startup, or CLI and loader will deadlock. */ 
							 
						 
					
						
							
								
									
										
										
										
											2025-07-21 13:12:40 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ast_fully_booted )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-03 12:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-30 18:30:18 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( type  = =  AST_MODULE_HELPER_LOAD )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-25 13:06:12 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										module_load_helper ( word ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-30 18:30:18 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_LOCK ( & module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_TRAVERSE ( & module_list ,  mod ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! module_matches_helper_type ( mod ,  type ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strncasecmp ( word ,  mod - > resource ,  wordlen )  & &  + + which  >  state )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ret  =  ast_strdup ( mod - > resource ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Merged revisions 199022 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
  r199022 | seanbright | 2009-06-04 10:14:57 -0400 (Thu, 04 Jun 2009) | 40 lines
  
  Safely handle AMI connections/reload requests that occur during startup.
  
  During asterisk startup, a lock on the list of modules is obtained by the
  primary thread while each module is initialized.  Issue 13778 pointed out a
  problem with this approach, however.  Because the AMI is loaded before other
  modules, it is possible for a module reload to be issued by a connected client
  (via Action: Command), causing a deadlock.
  
  The resolution for 13778 was to move initialization of the manager to happen
  after the other modules had already been lodaded.  While this fixed this
  particular issue, it caused a problem for users (like FreePBX) who call AMI
  scripts via an #exec in a configuration file (See issue 15189).
  
  The solution I have come up with is to defer any reload requests that come in
  until after the server is fully booted.  When a call comes in to
  ast_module_reload (from wherever) before we are fully booted, the request is
  added to a queue of pending requests.  Once we are done booting up, we then
  execute these deferred requests in turn.
  
  Note that I have tried to make this a bit more intelligent in that it will not
  queue up more than 1 request for the same module to be reloaded, and if a
  general reload request comes in ('module reload') the queue is flushed and we
  only issue a single deferred reload for the entire system.
  
  As for how this will impact existing installations - Before 13778, a reload
  issued before module initialization was completed would result in a deadlock.
  After 13778, you simply couldn't connect to the manager during startup (which
  causes problems with #exec-that-calls-AMI configuration files).  I believe this
  is a good general purpose solution that won't negatively impact existing
  installations.
  
  (closes issue #15189)
  (closes issue #13778)
  Reported by: p_lindheimer
  Patches:
        06032009_15189_deferred_reloads.diff uploaded by seanbright (license 71)
  Tested by: p_lindheimer, seanbright
  
  Review: https://reviewboard.asterisk.org/r/272/
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@199051 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2009-06-04 14:31:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_process_pending_reloads ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  reload_queue_item  * item ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-04-09 23:08:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									modules_loaded  =  1 ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Merged revisions 199022 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
  r199022 | seanbright | 2009-06-04 10:14:57 -0400 (Thu, 04 Jun 2009) | 40 lines
  
  Safely handle AMI connections/reload requests that occur during startup.
  
  During asterisk startup, a lock on the list of modules is obtained by the
  primary thread while each module is initialized.  Issue 13778 pointed out a
  problem with this approach, however.  Because the AMI is loaded before other
  modules, it is possible for a module reload to be issued by a connected client
  (via Action: Command), causing a deadlock.
  
  The resolution for 13778 was to move initialization of the manager to happen
  after the other modules had already been lodaded.  While this fixed this
  particular issue, it caused a problem for users (like FreePBX) who call AMI
  scripts via an #exec in a configuration file (See issue 15189).
  
  The solution I have come up with is to defer any reload requests that come in
  until after the server is fully booted.  When a call comes in to
  ast_module_reload (from wherever) before we are fully booted, the request is
  added to a queue of pending requests.  Once we are done booting up, we then
  execute these deferred requests in turn.
  
  Note that I have tried to make this a bit more intelligent in that it will not
  queue up more than 1 request for the same module to be reloaded, and if a
  general reload request comes in ('module reload') the queue is flushed and we
  only issue a single deferred reload for the entire system.
  
  As for how this will impact existing installations - Before 13778, a reload
  issued before module initialization was completed would result in a deadlock.
  After 13778, you simply couldn't connect to the manager during startup (which
  causes problems with #exec-that-calls-AMI configuration files).  I believe this
  is a good general purpose solution that won't negatively impact existing
  installations.
  
  (closes issue #15189)
  (closes issue #13778)
  Reported by: p_lindheimer
  Patches:
        06032009_15189_deferred_reloads.diff uploaded by seanbright (license 71)
  Tested by: p_lindheimer, seanbright
  
  Review: https://reviewboard.asterisk.org/r/272/
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@199051 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2009-06-04 14:31:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_LOCK ( & reload_queue ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( do_full_reload )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										do_full_reload  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_LIST_UNLOCK ( & reload_queue ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_NOTICE ,  " Executing deferred reload request. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_module_reload ( NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ( item  =  AST_LIST_REMOVE_HEAD ( & reload_queue ,  entry ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_NOTICE ,  " Executing deferred reload request for module '%s'. \n " ,  item - > module ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_module_reload ( item - > module ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_free ( item ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_UNLOCK ( & reload_queue ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  queue_reload_request ( const  char  * module )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  reload_queue_item  * item ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_LOCK ( & reload_queue ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( do_full_reload )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_LIST_UNLOCK ( & reload_queue ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( module ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* A full reload request (when module is NULL) wipes out any previous
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   reload  requests  and  causes  the  queue  to  ignore  future  ones  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										while  ( ( item  =  AST_LIST_REMOVE_HEAD ( & reload_queue ,  entry ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_free ( item ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										do_full_reload  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* No reason to add the same module twice */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_LIST_TRAVERSE ( & reload_queue ,  item ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! strcasecmp ( item - > module ,  module ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												AST_LIST_UNLOCK ( & reload_queue ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										item  =  ast_calloc ( 1 ,  sizeof ( * item )  +  strlen ( module )  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! item )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_ERROR ,  " Failed to allocate reload queue item. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_LIST_UNLOCK ( & reload_queue ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										strcpy ( item - > module ,  module ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_LIST_INSERT_TAIL ( & reload_queue ,  item ,  entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_UNLOCK ( & reload_queue ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-06 21:27:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Publish  a  \ ref  stasis  message  regarding  the  type . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-06 21:27:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  publish_load_message_type ( const  char *  type ,  const  char  * name ,  const  char  * status )  
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  stasis_message  * ,  message ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_json_payload  * ,  payload ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_json  * ,  json_object ,  NULL ,  ast_json_unref ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_json  * ,  event_object ,  NULL ,  ast_json_unref ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-06 21:27:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( type  ! =  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( ! ast_strlen_zero ( name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( ! ast_strlen_zero ( status ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-08-06 12:55:28 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ast_manager_get_generic_type ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-06 21:27:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									event_object  =  ast_json_pack ( " {s:s, s:s} " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" Module " ,  name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" Status " ,  status ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									json_object  =  ast_json_pack ( " {s:s, s:i, s:o} " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" type " ,  type , 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" class_type " ,  EVENT_FLAG_SYSTEM , 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-14 14:04:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" event " ,  ast_json_ref ( event_object ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! json_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									payload  =  ast_json_payload_create ( json_object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! payload )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									message  =  stasis_message_create ( ast_manager_get_generic_type ( ) ,  payload ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! message )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									stasis_publish ( ast_manager_get_topic ( ) ,  message ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-06 21:27:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  const  char *  loadresult2str ( enum  ast_module_load_result  result )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  ARRAY_LEN ( load_results ) ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( load_results [ i ] . result  = =  result )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  load_results [ i ] . name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_log ( LOG_WARNING ,  " Failed to find correct load result status. result %d \n " ,  result ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  AST_MODULE_LOAD_UNKNOWN_STRING ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Publish  a  \ ref  stasis  message  regarding  the  load  result 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  publish_load_message ( const  char  * name ,  enum  ast_module_load_result  result )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * status ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status  =  loadresult2str ( result ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									publish_load_message_type ( " Load " ,  name ,  status ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Publish  a  \ ref  stasis  message  regarding  the  unload  result 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  publish_unload_message ( const  char  * name ,  const  char *  status )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									publish_load_message_type ( " Unload " ,  name ,  status ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Publish  a  \ ref  stasis  message  regarding  the  reload  result 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  publish_reload_message ( const  char  * name ,  enum  ast_module_reload_result  result )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  res_buffer [ 8 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									snprintf ( res_buffer ,  sizeof ( res_buffer ) ,  " %u " ,  result ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									publish_load_message_type ( " Reload " ,  S_OR ( name ,  " All " ) ,  res_buffer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								enum  ast_module_reload_result  ast_module_reload ( const  char  * name )  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module  * cur ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_module_reload_result  res  =  AST_MODULE_RELOAD_NOT_FOUND ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									size_t  name_baselen  =  name  ?  resource_name_baselen ( name )  :  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Merged revisions 199022 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
  r199022 | seanbright | 2009-06-04 10:14:57 -0400 (Thu, 04 Jun 2009) | 40 lines
  
  Safely handle AMI connections/reload requests that occur during startup.
  
  During asterisk startup, a lock on the list of modules is obtained by the
  primary thread while each module is initialized.  Issue 13778 pointed out a
  problem with this approach, however.  Because the AMI is loaded before other
  modules, it is possible for a module reload to be issued by a connected client
  (via Action: Command), causing a deadlock.
  
  The resolution for 13778 was to move initialization of the manager to happen
  after the other modules had already been lodaded.  While this fixed this
  particular issue, it caused a problem for users (like FreePBX) who call AMI
  scripts via an #exec in a configuration file (See issue 15189).
  
  The solution I have come up with is to defer any reload requests that come in
  until after the server is fully booted.  When a call comes in to
  ast_module_reload (from wherever) before we are fully booted, the request is
  added to a queue of pending requests.  Once we are done booting up, we then
  execute these deferred requests in turn.
  
  Note that I have tried to make this a bit more intelligent in that it will not
  queue up more than 1 request for the same module to be reloaded, and if a
  general reload request comes in ('module reload') the queue is flushed and we
  only issue a single deferred reload for the entire system.
  
  As for how this will impact existing installations - Before 13778, a reload
  issued before module initialization was completed would result in a deadlock.
  After 13778, you simply couldn't connect to the manager during startup (which
  causes problems with #exec-that-calls-AMI configuration files).  I believe this
  is a good general purpose solution that won't negatively impact existing
  installations.
  
  (closes issue #15189)
  (closes issue #13778)
  Reported by: p_lindheimer
  Patches:
        06032009_15189_deferred_reloads.diff uploaded by seanbright (license 71)
  Tested by: p_lindheimer, seanbright
  
  Review: https://reviewboard.asterisk.org/r/272/
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@199051 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2009-06-04 14:31:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* If we aren't fully booted, we just pretend we reloaded but we queue this
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   up  to  run  once  we  are  booted  up .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2015-04-09 23:08:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! modules_loaded )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Merged revisions 199022 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
  r199022 | seanbright | 2009-06-04 10:14:57 -0400 (Thu, 04 Jun 2009) | 40 lines
  
  Safely handle AMI connections/reload requests that occur during startup.
  
  During asterisk startup, a lock on the list of modules is obtained by the
  primary thread while each module is initialized.  Issue 13778 pointed out a
  problem with this approach, however.  Because the AMI is loaded before other
  modules, it is possible for a module reload to be issued by a connected client
  (via Action: Command), causing a deadlock.
  
  The resolution for 13778 was to move initialization of the manager to happen
  after the other modules had already been lodaded.  While this fixed this
  particular issue, it caused a problem for users (like FreePBX) who call AMI
  scripts via an #exec in a configuration file (See issue 15189).
  
  The solution I have come up with is to defer any reload requests that come in
  until after the server is fully booted.  When a call comes in to
  ast_module_reload (from wherever) before we are fully booted, the request is
  added to a queue of pending requests.  Once we are done booting up, we then
  execute these deferred requests in turn.
  
  Note that I have tried to make this a bit more intelligent in that it will not
  queue up more than 1 request for the same module to be reloaded, and if a
  general reload request comes in ('module reload') the queue is flushed and we
  only issue a single deferred reload for the entire system.
  
  As for how this will impact existing installations - Before 13778, a reload
  issued before module initialization was completed would result in a deadlock.
  After 13778, you simply couldn't connect to the manager during startup (which
  causes problems with #exec-that-calls-AMI configuration files).  I believe this
  is a good general purpose solution that won't negatively impact existing
  installations.
  
  (closes issue #15189)
  (closes issue #13778)
  Reported by: p_lindheimer
  Patches:
        06032009_15189_deferred_reloads.diff uploaded by seanbright (license 71)
  Tested by: p_lindheimer, seanbright
  
  Review: https://reviewboard.asterisk.org/r/272/
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@199051 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2009-06-04 14:31:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										queue_reload_request ( name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  AST_MODULE_RELOAD_QUEUED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  module_reload_exit ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Merged revisions 199022 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
  r199022 | seanbright | 2009-06-04 10:14:57 -0400 (Thu, 04 Jun 2009) | 40 lines
  
  Safely handle AMI connections/reload requests that occur during startup.
  
  During asterisk startup, a lock on the list of modules is obtained by the
  primary thread while each module is initialized.  Issue 13778 pointed out a
  problem with this approach, however.  Because the AMI is loaded before other
  modules, it is possible for a module reload to be issued by a connected client
  (via Action: Command), causing a deadlock.
  
  The resolution for 13778 was to move initialization of the manager to happen
  after the other modules had already been lodaded.  While this fixed this
  particular issue, it caused a problem for users (like FreePBX) who call AMI
  scripts via an #exec in a configuration file (See issue 15189).
  
  The solution I have come up with is to defer any reload requests that come in
  until after the server is fully booted.  When a call comes in to
  ast_module_reload (from wherever) before we are fully booted, the request is
  added to a queue of pending requests.  Once we are done booting up, we then
  execute these deferred requests in turn.
  
  Note that I have tried to make this a bit more intelligent in that it will not
  queue up more than 1 request for the same module to be reloaded, and if a
  general reload request comes in ('module reload') the queue is flushed and we
  only issue a single deferred reload for the entire system.
  
  As for how this will impact existing installations - Before 13778, a reload
  issued before module initialization was completed would result in a deadlock.
  After 13778, you simply couldn't connect to the manager during startup (which
  causes problems with #exec-that-calls-AMI configuration files).  I believe this
  is a good general purpose solution that won't negatively impact existing
  installations.
  
  (closes issue #15189)
  (closes issue #13778)
  Reported by: p_lindheimer
  Patches:
        06032009_15189_deferred_reloads.diff uploaded by seanbright (license 71)
  Tested by: p_lindheimer, seanbright
  
  Review: https://reviewboard.asterisk.org/r/272/
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@199051 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2009-06-04 14:31:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ( ast_mutex_trylock ( & reloadlock ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-05-28 22:54:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_verb ( 3 ,  " The previous reload command didn't finish yet \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  AST_MODULE_RELOAD_IN_PROGRESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  module_reload_exit ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-05 14:53:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_sd_notify ( " RELOADING=1 " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-07-18 19:47:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_lastreloadtime  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-01-27 18:29:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_opt_lock_confdir )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  try ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-02 02:33:44 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										int  lockres ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  ( try  =  1 ,  lockres  =  AST_LOCK_TIMEOUT ;  try  <  6  & &  ( lockres  = =  AST_LOCK_TIMEOUT ) ;  try + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											lockres  =  ast_lock_path ( ast_config_AST_CONFIG_DIR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( lockres  = =  AST_LOCK_TIMEOUT )  { 
							 
						 
					
						
							
								
									
										
										
										
											2010-01-27 18:29:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												ast_log ( LOG_WARNING ,  " Failed to grab lock on %s, try %d \n " ,  ast_config_AST_CONFIG_DIR ,  try ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-02 02:33:44 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( lockres  ! =  AST_LOCK_SUCCESS )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-05-28 22:54:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_log ( AST_LOG_WARNING ,  " Cannot grab lock on %s \n " ,  ast_config_AST_CONFIG_DIR ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res  =  AST_MODULE_RELOAD_ERROR ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-27 21:26:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											goto  module_reload_done ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-01-27 18:29:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_LOCK ( & module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_TRAVERSE ( & module_list ,  cur ,  entry )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										const  struct  ast_module_info  * info  =  cur - > info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( name  & &  resource_name_match ( name ,  name_baselen ,  cur - > resource ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-02-15 19:50:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! cur - > flags . running  | |  cur - > flags . declined )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( res  = =  AST_MODULE_RELOAD_NOT_FOUND )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												res  =  AST_MODULE_RELOAD_UNINITIALIZED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! name )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-02-15 19:50:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2008-02-15 19:50:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! info - > reload )  { 	/* cannot be reloaded */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( res  = =  AST_MODULE_RELOAD_NOT_FOUND )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												res  =  AST_MODULE_RELOAD_NOT_IMPLEMENTED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2007-07-26 15:49:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_verb ( 3 ,  " Reloading module '%s' (%s) \n " ,  cur - > resource ,  info - > description ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( info - > reload ( )  = =  AST_MODULE_LOAD_SUCCESS )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											res  =  AST_MODULE_RELOAD_SUCCESS ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-02 02:33:44 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  if  ( res  = =  AST_MODULE_RELOAD_NOT_FOUND )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											res  =  AST_MODULE_RELOAD_ERROR ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-08-16 22:45:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-01-27 18:29:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_opt_lock_confdir )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_unlock_path ( ast_config_AST_CONFIG_DIR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-27 21:26:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								module_reload_done :  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ast_mutex_unlock ( & reloadlock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-27 21:26:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_sd_notify ( " READY=1 " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-24 20:44:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								module_reload_exit :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									publish_reload_message ( name ,  res ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  unsigned  int  inspect_module ( const  struct  ast_module  * mod )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! mod - > info - > description )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										module_load_error ( " Module '%s' does not provide a description. \n " ,  mod - > resource ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! mod - > info - > key )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										module_load_error ( " Module '%s' does not provide a license key. \n " ,  mod - > resource ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( verify_key ( ( unsigned  char  * )  mod - > info - > key ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										module_load_error ( " Module '%s' did not provide a valid license key. \n " ,  mod - > resource ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-11-20 19:28:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ast_strlen_zero ( mod - > info - > buildopt_sum )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    strcmp ( buildopt_sum ,  mod - > info - > buildopt_sum ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										module_load_error ( " Module '%s' was not compiled with the same compile-time options as this version of Asterisk. \n " ,  mod - > resource ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										module_load_error ( " Module '%s' will not be initialized as it may cause instability. \n " ,  mod - > resource ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-11-16 16:56:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  enum  ast_module_load_result  start_resource ( struct  ast_module  * mod )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  tmp [ 256 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									enum  ast_module_load_result  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-09-27 16:53:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( mod - > flags . running )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_MODULE_LOAD_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! mod - > info - > load )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-04 19:33:25 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mod - > flags . declined  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  mod - > flags . required  ?  AST_MODULE_LOAD_FAILURE  :  AST_MODULE_LOAD_DECLINE ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( module_deps_reference ( mod ,  NULL ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  module_vector  missing ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_VECTOR_INIT ( & missing ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( module_deps_missing_recursive ( mod ,  & missing ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											module_load_error ( " %s has one or more unknown dependencies. \n " ,  mod - > info - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  ( i  =  0 ;  i  <  AST_VECTOR_SIZE ( & missing ) ;  i + + )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											module_load_error ( " %s loaded before dependency %s! \n " ,  mod - > info - > name , 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												AST_VECTOR_GET ( & missing ,  i ) - > info - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_VECTOR_FREE ( & missing ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-24 23:44:09 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  AST_MODULE_LOAD_DECLINE ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-04-26 21:31:39 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ast_fully_booted )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 10:46:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_verb ( 4 ,  " Loading %s. \n " ,  mod - > resource ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-04-26 21:31:39 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									res  =  mod - > info - > load ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_MODULE_LOAD_SUCCESS : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! ast_fully_booted )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 10:46:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_verb ( 5 ,  " %s => (%s) \n " ,  mod - > resource ,  term_color ( tmp ,  mod - > info - > description ,  COLOR_BROWN ,  COLOR_BLACK ,  sizeof ( tmp ) ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 10:46:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_verb ( 4 ,  " Loaded %s => (%s) \n " ,  mod - > resource ,  mod - > info - > description ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mod - > flags . running  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 22:11:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( mod - > flags . builtin )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Built-in modules cannot be unloaded. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_module_shutdown_ref ( mod ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_update_use_count ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_MODULE_LOAD_DECLINE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mod - > flags . declined  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( mod - > flags . required )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											res  =  AST_MODULE_LOAD_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_MODULE_LOAD_FAILURE : 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-04 19:33:25 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mod - > flags . declined  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-22 15:33:35 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_MODULE_LOAD_SKIP :  /* modules should never return this value */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_MODULE_LOAD_PRIORITY : 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Make sure the newly started module is at the end of the list */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_LOCK ( & module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_REMOVE ( & module_list ,  mod ,  entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_INSERT_TAIL ( & module_list ,  mod ,  entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! loads a resource based upon resource_name. If global_symbols_only is set
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *   only  modules  with  global  symbols  will  be  loaded . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 01:28:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *   If  the  module_vector  is  provided  ( not  NULL )  the  module  is  found  and  added  to  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *   vector  without  running  the  module ' s  load ( )  function .   By  doing  this ,  modules 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *   can  be  initialized  later  in  order  by  priority  and  dependencies . 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 01:28:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *   If  the  module_vector  is  not  provided ,  the  module ' s  load  function  will  be  executed 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *   immediately  */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  enum  ast_module_load_result  load_resource ( const  char  * resource_name ,  unsigned  int  suppress_logging ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  module_vector  * module_priorities ,  int  required ,  int  preload ) 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module  * mod ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									enum  ast_module_load_result  res  =  AST_MODULE_LOAD_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( mod  =  find_resource ( resource_name ,  0 ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-03 16:43:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( mod - > flags . running )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-17 01:28:57 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_log ( LOG_WARNING ,  " Module '%s' already loaded and running. \n " ,  resource_name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											return  AST_MODULE_LOAD_DECLINE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 00:30:43 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mod  =  load_dynamic_module ( resource_name ,  suppress_logging ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-23 14:50:57 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! mod )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  required  ?  AST_MODULE_LOAD_FAILURE  :  AST_MODULE_LOAD_DECLINE ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-26 13:52:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( module_post_register ( mod ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-06 21:27:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											goto  prestart_error ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									mod - > flags . required  | =  required ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mod - > flags . preload  | =  preload ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ( inspect_module ( mod ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 01:28:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										goto  prestart_error ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-02-22 02:36:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-05-03 16:43:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									mod - > flags . declined  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 01:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( module_priorities )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( AST_VECTOR_ADD_SORTED ( module_priorities ,  mod ,  module_vector_cmp ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 01:28:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											goto  prestart_error ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-22 15:33:35 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  AST_MODULE_LOAD_PRIORITY ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  start_resource ( mod ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-06 21:27:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_fully_booted  & &  ! ast_shutdown_final ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										publish_load_message ( resource_name ,  res ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 01:28:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								prestart_error :  
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									module_load_error ( " Module '%s' could not be loaded. \n " ,  resource_name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 01:28:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									unload_dynamic_module ( mod ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-06 21:27:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									res  =  required  ?  AST_MODULE_LOAD_FAILURE  :  AST_MODULE_LOAD_DECLINE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_fully_booted  & &  ! ast_shutdown_final ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										publish_load_message ( resource_name ,  res ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-09 08:41:32 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								enum  ast_module_load_result  ast_load_resource ( const  char  * resource_name )  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2022-12-08 21:44:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_module  * mod ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-09 08:41:32 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_module_load_result  res ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 21:44:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If we're trying to load a module that previously declined to load,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  transparently  unload  it  first  so  we  dlclose ,  then  dlopen  it  afresh . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Otherwise ,  we  won ' t  actually  load  a  ( potentially )  updated  module .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mod  =  find_resource ( resource_name ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( mod  & &  mod - > flags . declined )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Module %s previously declined to load, unloading it first before loading again \n " ,  resource_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_unload_resource ( resource_name ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_LOCK ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									res  =  load_resource ( resource_name ,  0 ,  NULL ,  0 ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-08-16 22:45:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_suite_event_notify ( " MODULE_LOAD " ,  " Message: %s " ,  resource_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-06-05 15:58:11 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  load_order_entry  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * resource ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-13 08:52:28 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  required ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  preload ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  builtin ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									AST_LIST_ENTRY ( load_order_entry )  entry ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_LIST_HEAD_NOLOCK ( load_order ,  load_order_entry ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  struct  load_order_entry  * add_to_load_order ( const  char  * resource ,  struct  load_order  * load_order ,  int  required ,  int  preload ,  int  builtin )  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  load_order_entry  * order ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									size_t  resource_baselen  =  resource_name_baselen ( resource ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( load_order ,  order ,  entry )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! resource_name_match ( resource ,  resource_baselen ,  order - > resource ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2012-03-22 19:51:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/* Make sure we have the proper setting for the required field
 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-13 08:52:28 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											   ( we  might  have  both  load =  and  required =  lines  in  modules . conf )  */ 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-13 10:53:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											order - > required  | =  required ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											order - > preload  | =  preload ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  order ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-13 08:52:28 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									order  =  ast_calloc ( 1 ,  sizeof ( * order ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! order )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									order - > resource  =  ast_strdup ( resource ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-17 01:28:57 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! order - > resource )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_free ( order ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-13 08:52:28 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									order - > required  =  required ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									order - > preload  =  preload ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									order - > builtin  =  builtin ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									AST_LIST_INSERT_TAIL ( load_order ,  order ,  entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  order ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2008-06-12 17:27:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-01-23 14:50:57 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								AST_LIST_HEAD_NOLOCK ( load_retries ,  load_order_entry ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  enum  ast_module_load_result  start_resource_attempt ( struct  ast_module  * mod ,  int  * count )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									enum  ast_module_load_result  lres ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Try to grab required references. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( module_deps_reference ( mod ,  NULL ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* We're likely to retry so not an error. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Module %s is missing dependencies \n " ,  mod - > resource ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_MODULE_LOAD_SKIP ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									lres  =  start_resource ( mod ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_debug ( 3 ,  " START: %-46s[%d] %d \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mod - > resource , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_flag ( mod - > info ,  AST_MODFLAG_LOAD_ORDER )  ?  mod - > info - > load_pri  :  AST_MODPRI_DEFAULT , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										lres ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( lres  = =  AST_MODULE_LOAD_SUCCESS )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										( * count ) + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( lres  = =  AST_MODULE_LOAD_FAILURE )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										module_load_error ( " *** Failed to load %smodule %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											mod - > flags . required  ?  " required  "  :  " " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											mod - > resource ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  lres ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  resource_list_recursive_decline ( struct  module_vector  * resources ,  struct  ast_module  * mod ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_str  * * printmissing ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  module_vector  missingdeps ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_vector_const_string  localdeps ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mod - > flags . declined  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( mod - > flags . required )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										module_load_error ( " Required module %s declined to load. \n " ,  ast_module_name ( mod ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									module_load_error ( " %s declined to load. \n " ,  ast_module_name ( mod ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! * printmissing )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										* printmissing  =  ast_str_create ( 64 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! * printmissing )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_str_reset ( * printmissing ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_INIT ( & missingdeps ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_INIT ( & localdeps ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Decline everything that depends on 'mod' from resources so we can
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  print  a  concise  list .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( res  ! =  - 2  & &  i  <  AST_VECTOR_SIZE ( resources ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_module  * dep  =  AST_VECTOR_GET ( resources ,  i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										i + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_VECTOR_RESET ( & missingdeps ,  AST_VECTOR_ELEM_CLEANUP_NOOP ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( dep - > flags . declined  | |  module_deps_missing_recursive ( dep ,  & missingdeps ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( AST_VECTOR_GET_CMP ( & missingdeps ,  mod ,  AST_VECTOR_ELEM_DEFAULT_CMP ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											dep - > flags . declined  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( dep - > flags . required )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												module_load_error ( " Cannot load required module %s that depends on %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ast_module_name ( dep ) ,  ast_module_name ( mod ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												res  =  - 2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												AST_VECTOR_APPEND ( & localdeps ,  ast_module_name ( dep ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_FREE ( & missingdeps ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( res  ! =  - 2  & &  AST_VECTOR_SIZE ( & localdeps ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_VECTOR_CALLBACK_VOID ( & localdeps ,  STR_APPEND_TEXT ,  printmissing ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										module_load_error ( " Declined modules which depend on %s: %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_module_name ( mod ) ,  ast_str_buffer ( * printmissing ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_FREE ( & localdeps ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  start_resource_list ( struct  module_vector  * resources ,  int  * mod_count )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  module_vector  missingdeps ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_str  * printmissing  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_INIT ( & missingdeps ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									while  ( res  ! =  - 2  & &  AST_VECTOR_SIZE ( resources ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  ast_module  * mod  =  AST_VECTOR_REMOVE ( resources ,  0 ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										enum  ast_module_load_result  lres ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( mod - > flags . declined )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_debug ( 1 ,  " %s is already declined, skipping \n " ,  ast_module_name ( mod ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-24 23:44:09 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								retry_load :  
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										lres  =  start_resource_attempt ( mod ,  mod_count ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( lres  = =  AST_MODULE_LOAD_SUCCESS )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* No missing dependencies, successful. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( lres  = =  AST_MODULE_LOAD_FAILURE )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res  =  - 2 ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( lres  = =  AST_MODULE_LOAD_DECLINE )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res  =  resource_list_recursive_decline ( resources ,  mod ,  & printmissing ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( module_deps_missing_recursive ( mod ,  & missingdeps ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-24 23:44:09 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											AST_VECTOR_RESET ( & missingdeps ,  AST_VECTOR_ELEM_CLEANUP_NOOP ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											module_load_error ( " Failed to resolve dependencies for %s \n " ,  ast_module_name ( mod ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											res  =  resource_list_recursive_decline ( resources ,  mod ,  & printmissing ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-24 23:44:09 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! AST_VECTOR_SIZE ( & missingdeps ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											module_load_error ( " %s load function returned an invalid result.  " 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-24 23:44:09 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												" This is a bug in the module. \n " ,  ast_module_name ( mod ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Dependencies were met but the module failed to start and the result
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  code  was  not  AST_MODULE_LOAD_FAILURE  or  AST_MODULE_LOAD_DECLINE .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res  =  resource_list_recursive_decline ( resources ,  mod ,  & printmissing ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " %s has %d dependencies \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_module_name ( mod ) ,  ( int ) AST_VECTOR_SIZE ( & missingdeps ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										while  ( AST_VECTOR_SIZE ( & missingdeps ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											int  didwork  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											int  i  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											while  ( i  <  AST_VECTOR_SIZE ( & missingdeps ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												struct  ast_module  * dep  =  AST_VECTOR_GET ( & missingdeps ,  i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  ( dep - > flags . declined )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ast_debug ( 1 ,  " %s tried to start %s but it's already declined \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														ast_module_name ( mod ) ,  ast_module_name ( dep ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													i + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												ast_debug ( 1 ,  " %s trying to start %s \n " ,  ast_module_name ( mod ) ,  ast_module_name ( dep ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												lres  =  start_resource_attempt ( dep ,  mod_count ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( lres  = =  AST_MODULE_LOAD_SUCCESS )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													ast_debug ( 1 ,  " %s started %s \n " ,  ast_module_name ( mod ) ,  ast_module_name ( dep ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													AST_VECTOR_REMOVE ( & missingdeps ,  i ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													AST_VECTOR_REMOVE_CMP_ORDERED ( resources ,  dep , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														AST_VECTOR_ELEM_DEFAULT_CMP ,  AST_VECTOR_ELEM_CLEANUP_NOOP ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													didwork + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( lres  = =  AST_MODULE_LOAD_FAILURE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													module_load_error ( " Failed to load %s. \n " ,  ast_module_name ( dep ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													res  =  - 2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													goto  exitpoint ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												ast_debug ( 1 ,  " %s failed to start %s \n " ,  ast_module_name ( mod ) ,  ast_module_name ( dep ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												i + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! didwork )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( AST_VECTOR_SIZE ( & missingdeps ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! printmissing )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												printmissing  =  ast_str_create ( 64 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_str_reset ( printmissing ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( printmissing )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												struct  ast_vector_const_string  localdeps ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												AST_VECTOR_INIT ( & localdeps ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												module_deps_reference ( mod ,  & localdeps ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												AST_VECTOR_CALLBACK_VOID ( & localdeps ,  STR_APPEND_TEXT ,  & printmissing ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												AST_VECTOR_FREE ( & localdeps ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											module_load_error ( " Failed to load %s due to dependencies: %s. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_module_name ( mod ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												printmissing  ?  ast_str_buffer ( printmissing )  :  " allocation failure creating list " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											res  =  resource_list_recursive_decline ( resources ,  mod ,  & printmissing ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-24 23:44:09 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											AST_VECTOR_RESET ( & missingdeps ,  AST_VECTOR_ELEM_CLEANUP_NOOP ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-24 23:44:09 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-24 23:44:09 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* If we're here it means that we started with missingdeps and they're all loaded
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  now .   It ' s  impossible  to  reach  this  point  a  second  time  for  the  same  module .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  retry_load ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								exitpoint :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_free ( printmissing ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-22 00:39:33 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_VECTOR_FREE ( & missingdeps ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-03-22 19:51:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! loads modules in order by load_pri, updates mod_count
  
						 
					
						
							
								
									
										
										
										
											2009-11-13 08:52:28 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									\ return  - 1  on  failure  to  load  module ,  - 2  on  failure  to  load  required  module ,  otherwise  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								*/  
						 
					
						
							
								
									
										
										
										
											2017-12-09 00:30:43 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  load_resource_list ( struct  load_order  * load_order ,  int  * mod_count )  
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2017-12-09 01:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  module_vector  module_priorities ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  load_order_entry  * order ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 01:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  attempt  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  count  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 01:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  didwork ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  lasttry  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 01:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( AST_VECTOR_INIT ( & module_priorities ,  500 ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-21 01:28:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " Failed to initialize module loader. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									while  ( res  ! =  - 2 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 01:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										didwork  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-23 14:50:57 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 01:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										AST_LIST_TRAVERSE_SAFE_BEGIN ( load_order ,  order ,  entry )  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-23 14:50:57 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											enum  ast_module_load_result  lres ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Suppress log messages unless this is the last pass */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											lres  =  load_resource ( order - > resource ,  ! lasttry ,  & module_priorities ,  order - > required ,  order - > preload ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 01:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_debug ( 3 ,  " PASS %d: %-46s %d \n " ,  attempt ,  order - > resource ,  lres ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-23 14:50:57 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											switch  ( lres )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  AST_MODULE_LOAD_SUCCESS : 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 01:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											case  AST_MODULE_LOAD_SKIP : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* We're supplying module_priorities so SUCCESS isn't possible but we
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 *  still  have  to  test  for  it .   SKIP  is  only  used  when  we  try  to  start  a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 *  module  that  is  missing  dependencies .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-23 14:50:57 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											case  AST_MODULE_LOAD_DECLINE : 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												res  =  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-23 14:50:57 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  AST_MODULE_LOAD_FAILURE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* LOAD_FAILURE only happens for required modules */ 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 01:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  ( lasttry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													/* This run is just to print errors. */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													module_load_error ( " *** Failed to load module %s - Required \n " ,  order - > resource ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-23 14:50:57 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													fprintf ( stderr ,  " *** Failed to load module %s - Required \n " ,  order - > resource ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													res  =   - 2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  AST_MODULE_LOAD_PRIORITY : 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 01:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												/* load_resource worked and the module was added to module_priorities */ 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-23 14:50:57 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												AST_LIST_REMOVE_CURRENT ( entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_free ( order - > resource ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_free ( order ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 01:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												didwork  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-23 14:50:57 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_LIST_TRAVERSE_SAFE_END ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 01:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! didwork )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( lasttry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* We know the next try is going to fail, it's only being performed
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  so  we  can  print  errors .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											lasttry  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										attempt + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( res  ! =  - 2 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 01:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  start_resource_list ( & module_priorities ,  & count ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-23 14:50:57 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( mod_count )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										* mod_count  + =  count ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 01:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_VECTOR_FREE ( & module_priorities ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-09 16:22:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  loader_builtin_init ( struct  load_order  * load_order )  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_module  * mod ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-29 23:00:52 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  All  built - in  modules  have  registered  the  first  time ,  now  it ' s  time  to  complete 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  the  registration  and  add  them  to  the  priority  list . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									loader_ready  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ( resource_being_loaded  =  AST_DLLIST_REMOVE_HEAD ( & builtin_module_list ,  entry ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* ast_module_register doesn't finish when first run by built-in modules. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_module_register ( resource_being_loaded - > info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Add all built-in modules to the load order. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_TRAVERSE ( & module_list ,  mod ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! mod - > flags . builtin )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 22:11:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
											
												docs: Fix various typos in main/
Found via `codespell -q 3 -S "./CREDITS" -L abd,asent,atleast,childrens,contentn,crypted,dne,durationm,exten,inout,leapyear,nd,oclock,offsetp,ot,parm,parms,requestor,ser,slanguage,slin,thirdparty,varn,varns,ues`
											 
										 
										
											2025-02-04 05:53:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Parse dependencies from mod->info. */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-26 13:52:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( module_post_register ( mod ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Built-in modules are not preloaded, most have an early load priority. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! add_to_load_order ( mod - > resource ,  load_order ,  0 ,  0 ,  1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 22:11:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  loader_config_init ( struct  load_order  * load_order )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  load_order_entry  * order ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_config  * cfg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_variable  * v ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_flags  config_flags  =  {  0  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-09-12 23:30:03 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cfg  =  ast_config_load2 ( AST_MODULE_CONFIG ,  " "  /* core, can't reload */ ,  config_flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cfg  = =  CONFIG_STATUS_FILEMISSING  | |  cfg  = =  CONFIG_STATUS_FILEINVALID )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_log ( LOG_WARNING ,  " '%s' invalid or missing. \n " ,  AST_MODULE_CONFIG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-22 23:06:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* first, find all the modules we have been explicitly requested to load */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( v  =  ast_variable_browse ( cfg ,  " modules " ) ;  v ;  v  =  v - > next )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										int  required ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  preload  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strncasecmp ( v - > name ,  " preload " ,  strlen ( " preload " ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											preload  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! strcasecmp ( v - > name ,  " preload " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												required  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  if  ( ! strcasecmp ( v - > name ,  " preload-require " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												required  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_log ( LOG_ERROR ,  " Unknown configuration option '%s' " ,  v - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												goto  done ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( ! strcasecmp ( v - > name ,  " load " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											required  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( ! strcasecmp ( v - > name ,  " require " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											required  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( ! strcasecmp ( v - > name ,  " noload " )  | |  ! strcasecmp ( v - > name ,  " autoload " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_ERROR ,  " Unknown configuration option '%s' " ,  v - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  done ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-13 08:52:28 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( required )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-13 08:52:28 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_debug ( 2 ,  " Adding module to required list: %s (%s) \n " ,  v - > value ,  v - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-06-12 17:27:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! add_to_load_order ( v - > value ,  load_order ,  required ,  preload ,  0 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  done ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* check if 'autoload' is on */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_true ( ast_variable_retrieve ( cfg ,  " modules " ,  " autoload " ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										/* if we are allowed to load dynamic modules, scan the directory for
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   for  all  available  modules  and  add  them  as  well  */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										DIR  * dir  =  opendir ( ast_config_AST_MODULE_DIR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  dirent  * dirent ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( dir )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											while  ( ( dirent  =  readdir ( dir ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												int  ld  =  strlen ( dirent - > d_name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-09-15 05:00:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												/* Must end in .so to load it.  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( ld  <  4 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( strcasecmp ( dirent - > d_name  +  ld  -  3 ,  " .so " ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-03 16:43:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													continue ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-05-03 16:43:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												/* if there is already a module by this name in the module_list,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												   skip  this  file  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( find_resource ( dirent - > d_name ,  0 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  ( ! add_to_load_order ( dirent - > d_name ,  load_order ,  0 ,  0 ,  0 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													closedir ( dir ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													goto  done ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											closedir ( dir ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_log ( LOG_ERROR ,  " Unable to open modules directory '%s'. \n " ,  ast_config_AST_MODULE_DIR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  done ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* now scan the config for any modules we are prohibited from loading and
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   remove  them  from  the  load  order  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( v  =  ast_variable_browse ( cfg ,  " modules " ) ;  v ;  v  =  v - > next )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										size_t  baselen ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( strcasecmp ( v - > name ,  " noload " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										baselen  =  resource_name_baselen ( v - > value ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										AST_LIST_TRAVERSE_SAFE_BEGIN ( load_order ,  order ,  entry )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:19:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! resource_name_match ( v - > value ,  baselen ,  order - > resource ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  ( order - > builtin )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ast_log ( LOG_ERROR ,  " %s is a built-in module, you cannot specify 'noload'. \n " ,  v - > value ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													goto  done ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( order - > required )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ast_log ( LOG_ERROR ,  " %s is configured with '%s' and 'noload', this is impossible. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														v - > value ,  order - > preload  ?  " preload-require "  :  " require " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													goto  done ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2007-11-08 05:28:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												AST_LIST_REMOVE_CURRENT ( entry ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-06 21:20:11 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												ast_free ( order - > resource ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_free ( order ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_LIST_TRAVERSE_SAFE_END ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									res  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								done :  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ast_config_destroy ( cfg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  load_modules ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  load_order_entry  * order ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  int  load_count ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  load_order  load_order ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  modulecount  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-10 11:03:11 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_module  * cur ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef AST_XML_DOCS 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_str  * warning_msg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  deprecated_in [ 33 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  removed_in [ 33 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  replacement [ 129 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  timeval  start_time  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  timeval  end_time ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int64_t  usElapsed ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_verb ( 1 ,  " Asterisk Dynamic Loader Starting: \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-02 22:49:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# if defined(HAVE_PERMANENT_DLOPEN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									info_list  =  ao2_container_alloc_list ( AO2_ALLOC_OPT_LOCK_NOLOCK ,  0 ,  NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info_list_obj_cmp_fn ) ;  /* must not be cleaned at shutdown */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! info_list )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fprintf ( stderr ,  " Module info list allocation failure. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_LIST_HEAD_INIT_NOLOCK ( & load_order ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_LOCK ( & module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_VECTOR_INIT ( & startup_errors ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									startup_error_builder  =  ast_str_create ( 64 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 14:58:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									res  =  loader_builtin_init ( & load_order ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  done ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  loader_config_init ( & load_order ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  done ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									load_count  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( & load_order ,  order ,  entry ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										load_count + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-22 23:06:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( load_count ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-05-09 22:49:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_log ( LOG_NOTICE ,  " %u modules will be loaded. \n " ,  load_count ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-09 00:30:43 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									res  =  load_resource_list ( & load_order ,  & modulecount ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( res  = =  - 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_WARNING ,  " Some non-required modules failed to load. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								done :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ( order  =  AST_LIST_REMOVE_HEAD ( & load_order ,  entry ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-06 21:20:11 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_free ( order - > resource ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_free ( order ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-10 11:03:11 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# ifdef AST_XML_DOCS 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									warning_msg  =  ast_str_create ( 512 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_TRAVERSE ( & module_list ,  cur ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef AST_XML_DOCS 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										char  * mod_name  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_xml_xpath_results  * results ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! cur - > flags . running  | |  cur - > flags . declined )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef AST_XML_DOCS 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mod_name  =  get_name_from_resource ( cur - > resource ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! warning_msg  | |  ! mod_name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* If we can't allocate memory, we have bigger issues */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_free ( mod_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 11:38:04 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Clear out the previous values */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										deprecated_in [ 0 ]  =  removed_in [ 0 ]  =  replacement [ 0 ]  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										results  =  ast_xmldoc_query ( " /docs/module[@name='%s'] " ,  mod_name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-10 11:03:11 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( results )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 11:38:04 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											struct  ast_xml_node  * deprecated_node ,  * removed_node ,  * replacement_node ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_xml_node  * metadata_nodes  =  ast_xml_node_get_children ( ast_xml_xpath_get_first_result ( results ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											deprecated_node  =  ast_xml_find_element ( metadata_nodes ,  " deprecated_in " ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( deprecated_node )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												const  char  * result_tmp  =  ast_xml_get_text ( deprecated_node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( ! ast_strlen_zero ( result_tmp ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ast_copy_string ( deprecated_in ,  result_tmp ,  sizeof ( deprecated_in ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-10 11:03:11 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 11:38:04 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											removed_node  =  ast_xml_find_element ( metadata_nodes ,  " removed_in " ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( removed_node )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												const  char  * result_tmp  =  ast_xml_get_text ( removed_node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( ! ast_strlen_zero ( result_tmp ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ast_copy_string ( removed_in ,  result_tmp ,  sizeof ( removed_in ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-10 11:03:11 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 11:38:04 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											replacement_node  =  ast_xml_find_element ( metadata_nodes ,  " replacement " ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( replacement_node )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												const  char  * result_tmp  =  ast_xml_get_text ( replacement_node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( ! ast_strlen_zero ( result_tmp ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ast_copy_string ( replacement ,  result_tmp ,  sizeof ( replacement ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-10 11:03:11 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 11:38:04 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-10 11:03:11 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_xml_xpath_results_free ( results ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_str_reset ( warning_msg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cur - > info - > support_level  = =  AST_MODULE_SUPPORT_DEPRECATED  | |  ! ast_strlen_zero ( deprecated_in ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											| |  ! ast_strlen_zero ( removed_in )  | |  ! ast_strlen_zero ( replacement ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											int  already_butted  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_str_append ( & warning_msg ,  - 1 ,  " Module '%s' has been loaded " ,  mod_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! ast_strlen_zero ( deprecated_in ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_str_append ( & warning_msg ,  - 1 ,  "  but %s deprecated in Asterisk version %s " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 cur - > info - > support_level  = =  AST_MODULE_SUPPORT_DEPRECATED  ?  " was "  :  " will be " ,  deprecated_in ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												already_butted  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! ast_strlen_zero ( removed_in ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_str_append ( & warning_msg ,  - 1 ,  "  %s will be removed in Asterisk version %s " ,  already_butted  ?  " and "  :  " but " ,  removed_in ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_str_append ( & warning_msg ,  - 1 ,  "  %s may be removed in a future release " ,  already_butted  ?  " and "  :  " but " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_str_append ( & warning_msg ,  - 1 ,  " . " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! ast_strlen_zero ( replacement ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_str_append ( & warning_msg ,  - 1 ,  "  Its replacement is '%s'. " ,  replacement ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_str_strlen ( warning_msg ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_WARNING ,  " %s \n " ,  ast_str_buffer ( warning_msg ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_free ( mod_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cur - > info - > support_level  = =  AST_MODULE_SUPPORT_DEPRECATED )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_WARNING ,  " The deprecated module '%s' has been loaded and is running, it may be removed in a future version \n " ,  cur - > resource ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef AST_XML_DOCS 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_free ( warning_msg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-10 11:03:11 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-28 11:13:39 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  AST_VECTOR_SIZE ( & startup_errors ) ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										char  * str  =  AST_VECTOR_GET ( & startup_errors ,  i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " %s " ,  str ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_free ( str ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_FREE ( & startup_errors ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_free ( startup_error_builder ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									startup_error_builder  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-10 11:03:11 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									end_time  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usElapsed  =  ast_tvdiff_us ( end_time ,  start_time ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef AST_XML_DOCS 
  
						 
					
						
							
								
									
										
										
										
											2022-05-17 10:18:58 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Loader time with AST_XML_DOCS: % "  PRId64  " .%06 "  PRId64  " \n " ,  usElapsed  /  1000000 ,  usElapsed  %  1000000 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-10 11:03:11 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
									
										
										
										
											2022-05-17 10:18:58 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Loader time without AST_XML_DOCS: % "  PRId64  " .%06 "  PRId64  " \n " ,  usElapsed  /  1000000 ,  usElapsed  %  1000000 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-10 11:03:11 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_update_use_count ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2006-09-15 05:00:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Notify any module monitors that the use count for a
 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									   resource  has  changed  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  loadupdate  * m ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-02-27 17:12:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_LIST_LOCK ( & updaters ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( & updaters ,  m ,  entry ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										m - > updater ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-02-27 17:12:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_LIST_UNLOCK ( & updaters ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Build  an  alpha  sorted  list  of  modules . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  alpha_module_list  Pointer  to  uninitialized  module_vector . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  function  always  initializes  alpha_module_list . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ pre  module_list  must  be  locked . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  alpha_module_list_create ( struct  module_vector  * alpha_module_list )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module  * cur ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( AST_VECTOR_INIT ( alpha_module_list ,  32 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_TRAVERSE ( & module_list ,  cur ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( AST_VECTOR_ADD_SORTED ( alpha_module_list ,  cur ,  module_vector_strcasecmp ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-07-25 16:47:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_update_module_list ( int  ( * modentry ) ( const  char  * module ,  const  char  * description ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                           int  usecnt ,  const  char  * status ,  const  char  * like , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
																		   enum  ast_module_support_level  support_level ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                           const  char  * like ) 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  total_mod_loaded  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  module_vector  alpha_module_list ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_LOCK ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-03-22 19:51:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! alpha_module_list_create ( & alpha_module_list ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  idx ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  ( idx  =  0 ;  idx  <  AST_VECTOR_SIZE ( & alpha_module_list ) ;  idx + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_module  * cur  =  AST_VECTOR_GET ( & alpha_module_list ,  idx ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											total_mod_loaded  + =  modentry ( cur - > resource ,  cur - > info - > description ,  cur - > usecount , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cur - > flags . running  ?  " Running "  :  " Not Running " ,  like ,  cur - > info - > support_level ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												module loader: Unload modules in reverse order of their start order
When Asterisk starts a module (calling its load_module function), it re-orders
the module list, sorting it alphabetically. Ostensibly, this was done so that
the output of 'module show' listed modules in alphabetic order. This had the
unfortunate side effect of making modules with complex usage patterns
unloadable. A module that has a large number of modules that depend on it is
typically abandoned during the unloading process. This results in its memory
not being reclaimed during exit.
Generally, this isn't harmful - when the process is destroyed, the operating
system will reclaim all memory allocated by the process. Prior to Asterisk 12,
we also didn't have many modules with complex dependencies. However, with
the advent of ARI and PJSIP, this can make make unloading those modules
successfully nearly impossible, and thus tracking memory leaks or ref debug
leaks a real pain.
While this patch is not a complete overhaul of the module loader - such an
effort would be beyond the scope of what could be done for Asterisk 13 -
this does make some marginal improvements to the loader such that modules
like res_pjsip or res_stasis *may* be made properly un-loadable in the future.
1. The linked list of modules has been replaced with a doubly linked list. This
   allows traversal of the module list to occur backwards. The module shutdown
   routine now walks the global list backwards when it attempts to unload
   modules.
2. The alphabetic reorganization of the module list on startup has been
   removed. Instead, a started module is placed at the end of the module list.
3. The ast_update_module_list function - which is used by the CLI to display
   the modules - now does the sorting alphabetically itself. It creates its own
   linked list and inserts the modules into it in alphabetic order. This allows
   for the intent of the previous code to be maintained.
This patch also contains a fix for res_calendar. Without calendar.conf, the
calendar modules were improperly bumping the use count of res_calendar, then
failing to load themselves. This patch makes it so that we detect whether or
not calendaring is enabled before altering the use count.
Review: https://reviewboard.asterisk.org/r/3777/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-25 14:27:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_VECTOR_FREE ( & alpha_module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  total_mod_loaded ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-06-26 10:57:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_update_module_list_data ( int  ( * modentry ) ( const  char  * module ,  const  char  * description ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                int  usecnt ,  const  char  * status ,  const  char  * like , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                enum  ast_module_support_level  support_level , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                void  * data ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                const  char  * like ,  void  * data ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  total_mod_loaded  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  module_vector  alpha_module_list ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-26 10:57:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_LOCK ( & module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! alpha_module_list_create ( & alpha_module_list ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  idx ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-26 10:57:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  ( idx  =  0 ;  idx  <  AST_VECTOR_SIZE ( & alpha_module_list ) ;  idx + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_module  * cur  =  AST_VECTOR_GET ( & alpha_module_list ,  idx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											total_mod_loaded  + =  modentry ( cur - > resource ,  cur - > info - > description ,  cur - > usecount , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cur - > flags . running ?  " Running "  :  " Not Running " ,  like ,  cur - > info - > support_level ,  data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-26 10:57:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_VECTOR_FREE ( & alpha_module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-26 10:57:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  total_mod_loaded ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-07-13 10:54:51 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_update_module_list_condition ( int  ( * modentry ) ( const  char  * module ,  const  char  * description ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                     int  usecnt ,  const  char  * status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                     const  char  * like , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                     enum  ast_module_support_level  support_level , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                     void  * data ,  const  char  * condition ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                     const  char  * like ,  void  * data ,  const  char  * condition ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  conditions_met  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  module_vector  alpha_module_list ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-13 10:54:51 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_LOCK ( & module_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! alpha_module_list_create ( & alpha_module_list ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  idx ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-13 10:54:51 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  ( idx  =  0 ;  idx  <  AST_VECTOR_SIZE ( & alpha_module_list ) ;  idx + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_module  * cur  =  AST_VECTOR_GET ( & alpha_module_list ,  idx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											conditions_met  + =  modentry ( cur - > resource ,  cur - > info - > description ,  cur - > usecount , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cur - > flags . running ?  " Running "  :  " Not Running " ,  like ,  cur - > info - > support_level ,  data , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												condition ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-13 10:54:51 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DLLIST_UNLOCK ( & module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-11 18:07:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_VECTOR_FREE ( & alpha_module_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-13 10:54:51 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  conditions_met ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-10-31 08:08:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief Check if module exists */  
						 
					
						
							
								
									
										
										
										
											2007-05-07 19:03:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_module_check ( const  char  * name )  
						 
					
						
							
								
									
										
										
										
											2006-10-30 21:48:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_module  * cur ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( name ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ;        /* FALSE */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-10-31 08:08:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cur  =  find_resource ( name ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ( cur  ! =  NULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-10-30 21:48:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-09-15 05:00:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_loader_register ( int  ( * v ) ( void ) )  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2006-09-15 05:00:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  loadupdate  * tmp ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ( tmp  =  ast_malloc ( sizeof ( * tmp ) ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tmp - > updater  =  v ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-02-27 17:12:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_LIST_LOCK ( & updaters ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									AST_LIST_INSERT_HEAD ( & updaters ,  tmp ,  entry ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-02-27 17:12:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_LIST_UNLOCK ( & updaters ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_loader_unregister ( int  ( * v ) ( void ) )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  loadupdate  * cur ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-02-27 17:12:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_LIST_LOCK ( & updaters ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE_SAFE_BEGIN ( & updaters ,  cur ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cur - > updater  = =  v ) 	{ 
							 
						 
					
						
							
								
									
										
										
										
											2007-11-08 05:28:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											AST_LIST_REMOVE_CURRENT ( entry ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE_SAFE_END ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-02-27 17:12:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_LIST_UNLOCK ( & updaters ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cur  ?  0  :  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-02-11 17:03:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_module  * __ast_module_ref ( struct  ast_module  * mod ,  const  char  * file ,  int  line ,  const  char  * func )  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2010-02-17 07:01:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! mod )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-04-17 03:16:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( mod - > ref_debug )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										__ao2_ref ( mod - > ref_debug ,  + 1 ,  " " ,  file ,  line ,  func ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-11 17:03:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ast_atomic_fetchadd_int ( & mod - > usecount ,  + 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_update_use_count ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  mod ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-29 19:24:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_module  * __ast_module_running_ref ( struct  ast_module  * mod ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * file ,  int  line ,  const  char  * func ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! mod  | |  ! mod - > flags . running )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  __ast_module_ref ( mod ,  file ,  line ,  func ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-02-11 17:03:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  __ast_module_shutdown_ref ( struct  ast_module  * mod ,  const  char  * file ,  int  line ,  const  char  * func )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2015-02-21 02:58:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! mod  | |  mod - > flags . keepuntilshutdown )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-11 17:03:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-21 02:58:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									__ast_module_ref ( mod ,  file ,  line ,  func ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mod - > flags . keepuntilshutdown  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-11 17:03:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  __ast_module_unref ( struct  ast_module  * mod ,  const  char  * file ,  int  line ,  const  char  * func )  
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2010-02-17 07:01:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! mod )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-04-17 03:16:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( mod - > ref_debug )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										__ao2_ref ( mod - > ref_debug ,  - 1 ,  " " ,  file ,  line ,  func ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-11 17:03:04 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-08-21 02:11:39 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ast_atomic_fetchadd_int ( & mod - > usecount ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_update_use_count ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2014-07-25 16:47:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  char  * support_level_map  [ ]  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									[ AST_MODULE_SUPPORT_UNKNOWN ]  =  " unknown " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									[ AST_MODULE_SUPPORT_CORE ]  =  " core " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									[ AST_MODULE_SUPPORT_EXTENDED ]  =  " extended " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									[ AST_MODULE_SUPPORT_DEPRECATED ]  =  " deprecated " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  char  * ast_module_support_level_to_string ( enum  ast_module_support_level  support_level )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  support_level_map [ support_level ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}