@ -53,6 +53,7 @@ struct plugins *plugins_new(const tal_t *ctx, struct log_book *log_book,
p - > startup = true ;
p - > json_cmds = tal_arr ( p , struct command * , 0 ) ;
p - > blacklist = tal_arr ( p , const char * , 0 ) ;
p - > shutdown = false ;
uintmap_init ( & p - > pending_requests ) ;
memleak_add_helper ( p , memleak_help_pending_requests ) ;
@ -62,6 +63,9 @@ struct plugins *plugins_new(const tal_t *ctx, struct log_book *log_book,
void plugins_free ( struct plugins * plugins )
{
struct plugin * p ;
plugins - > shutdown = true ;
/* Plugins are usually the unit of allocation, and they are internally
* consistent , so let ' s free each plugin first . */
while ( ! list_empty ( & plugins - > plugins ) ) {
@ -105,6 +109,7 @@ struct command_result *plugin_register_all_complete(struct lightningd *ld,
static void destroy_plugin ( struct plugin * p )
{
struct plugin_rpccall * call ;
plugin_hook_unregister_all ( p ) ;
list_del ( & p - > list ) ;
@ -118,10 +123,23 @@ static void destroy_plugin(struct plugin *p)
/* Don't call this if we're still parsing options! */
if ( p - > plugin_state ! = UNCONFIGURED )
check_plugins_resolved ( p - > plugins ) ;
/* If we are shutting down, do not continue to checking if
* the dying plugin is important . */
if ( p - > plugins - > shutdown )
return ;
/* Now check if the dying plugin is important. */
if ( p - > important ) {
log_broken ( p - > log ,
" Plugin marked as important, "
" shutting down lightningd! " ) ;
lightningd_exit ( p - > plugins - > ld , 1 ) ;
}
}
struct plugin * plugin_register ( struct plugins * plugins , const char * path TAKES ,
struct command * start_cmd )
struct command * start_cmd , bool important )
{
struct plugin * p , * p_temp ;
@ -130,6 +148,9 @@ struct plugin *plugin_register(struct plugins *plugins, const char* path TAKES,
if ( streq ( path , p_temp - > cmd ) ) {
if ( taken ( path ) )
tal_free ( path ) ;
/* If added as "important", upgrade to "important". */
if ( important )
p_temp - > important = true ;
return NULL ;
}
}
@ -153,6 +174,8 @@ struct plugin *plugin_register(struct plugins *plugins, const char* path TAKES,
list_add_tail ( & plugins - > plugins , & p - > list ) ;
tal_add_destructor ( p , destroy_plugin ) ;
list_head_init ( & p - > pending_rpccalls ) ;
p - > important = important ;
return p ;
}
@ -186,6 +209,8 @@ void plugin_blacklist(struct plugins *plugins, const char *name)
log_info ( plugins - > log , " %s: disabled via disable-plugin " ,
p - > cmd ) ;
list_del_from ( & plugins - > plugins , & p - > list ) ;
/* disable-plugin overrides important-plugin. */
p - > important = false ;
tal_free ( p ) ;
}
}
@ -1188,7 +1213,7 @@ char *add_plugin_dir(struct plugins *plugins, const char *dir, bool error_ok)
log_info ( plugins - > log , " %s: disabled via disable-plugin " ,
fullpath ) ;
} else {
p = plugin_register ( plugins , fullpath , NULL ) ;
p = plugin_register ( plugins , fullpath , NULL , false ) ;
if ( ! p & & ! error_ok )
return tal_fmt ( NULL , " Failed to register %s: %s " ,
fullpath , strerror ( errno ) ) ;
@ -1396,24 +1421,35 @@ void plugins_config(struct plugins *plugins)
plugins - > startup = false ;
}
void json_add_opt_plugins ( struct json_stream * response ,
const struct plugins * plugins )
/** json_add_opt_plugins_array
*
* @ brief add a named array of plugins to the given response ,
* depending on whether it is important or not important .
*
* @ param response - the ` json_stream ` to write into .
* @ param name - the field name of the array .
* @ param plugins - the plugins object to query .
* @ param important - match the ` important ` setting of the
* plugins to be added .
*/
static
void json_add_opt_plugins_array ( struct json_stream * response ,
const char * name ,
const struct plugins * plugins ,
bool important )
{
struct plugin * p ;
struct plugin_opt * opt ;
const char * plugin_name ;
struct plugin_opt * opt ;
const char * opt_name ;
/* DEPRECATED: duplicated JSON "plugin" entries */
if ( deprecated_apis ) {
list_for_each ( & plugins - > plugins , p , list ) {
json_add_string ( response , " plugin " , p - > cmd ) ;
}
}
/* we output 'plugins' and their options as an array of substructures */
json_array_start ( response , " plugins " ) ;
json_array_start ( response , name ) ;
list_for_each ( & plugins - > plugins , p , list ) {
/* Skip if not matching. */
if ( p - > important ! = important )
continue ;
json_object_start ( response , NULL ) ;
json_add_string ( response , " path " , p - > cmd ) ;
@ -1444,6 +1480,23 @@ void json_add_opt_plugins(struct json_stream *response,
json_array_end ( response ) ;
}
void json_add_opt_plugins ( struct json_stream * response ,
const struct plugins * plugins )
{
struct plugin * p ;
json_add_opt_plugins_array ( response , " plugins " , plugins , false ) ;
json_add_opt_plugins_array ( response , " important-plugins " , plugins , true ) ;
/* DEPRECATED: duplicated JSON "plugin" entries */
if ( deprecated_apis ) {
list_for_each ( & plugins - > plugins , p , list ) {
json_add_string ( response , p - > important ? " important-plugin " : " plugin " , p - > cmd ) ;
}
}
}
void json_add_opt_disable_plugins ( struct json_stream * response ,
const struct plugins * plugins )
{
@ -1546,7 +1599,6 @@ static void mark_plugin_destroyed(const struct plugin *unused,
pd - > plugin = NULL ;
}
struct plugin_destroyed * plugin_detect_destruction ( const struct plugin * plugin )
{
struct plugin_destroyed * pd = tal ( NULL , struct plugin_destroyed ) ;