config: Allow options to register when documentation is unavailable.

The config options framework is strict in that configuration options must
be documented unless XML documentation support is not available. In
practice this is useful as it ensures documentation exists however in
off-nominal cases this can cause strange problems.

If it is expected that a config option has a non-zero or non-empty
default value but the config option documentation is unavailable
this reasonable expectation will not be met. This can cause obscure
crashes and weirdness depending on how the code handles it.

This change tweaks the behavior to ensure that the config option
is still allowed to register, apply default values, and be set when
devmode is not enabled. If devmode is enabled then the option can
NOT be set.

This also does not remove the initial documentation error message that
is output on load when registering the configuration option.

ASTERISK-25725 #close

Change-Id: Iec42fca6b35f31326c33fcdc25473f6fd7bc8af8
(cherry picked from commit f22074e5d9)
changes/37/2137/1
Joshua Colp 9 years ago
parent 22eb1b48c0
commit 7d581b32e9

@ -71,6 +71,9 @@ struct aco_option {
aco_option_handler handler; aco_option_handler handler;
unsigned int flags; unsigned int flags;
unsigned int no_doc:1; unsigned int no_doc:1;
#ifdef AST_DEVMODE
unsigned int doc_unavailable:1;
#endif
unsigned char deprecated:1; unsigned char deprecated:1;
size_t argc; size_t argc;
intptr_t args[0]; intptr_t args[0];
@ -183,18 +186,20 @@ static int link_option_to_types(struct aco_info *info, struct aco_type **types,
ast_log(LOG_ERROR, "Attempting to register option using uninitialized type\n"); ast_log(LOG_ERROR, "Attempting to register option using uninitialized type\n");
return -1; return -1;
} }
if (!ao2_link(type->internal->opts, opt) if (!ao2_link(type->internal->opts, opt)) {
#ifdef AST_XML_DOCS
|| (!info->hidden &&
!opt->no_doc &&
xmldoc_update_config_option(types, info->module, opt->name, type->name, opt->default_val, opt->match_type == ACO_REGEX, opt->type))
#endif /* AST_XML_DOCS */
) {
do { do {
ao2_unlink(types[idx - 1]->internal->opts, opt); ao2_unlink(types[idx - 1]->internal->opts, opt);
} while (--idx); } while (--idx);
return -1; return -1;
} }
#ifdef AST_XML_DOCS
if (!info->hidden && !opt->no_doc &&
xmldoc_update_config_option(types, info->module, opt->name, type->name, opt->default_val, opt->match_type == ACO_REGEX, opt->type)) {
#ifdef AST_DEVMODE
opt->doc_unavailable = 1;
#endif
#endif
}
} }
/* The container(s) should hold the only ref to opt */ /* The container(s) should hold the only ref to opt */
ao2_ref(opt, -1); ao2_ref(opt, -1);
@ -716,6 +721,14 @@ int aco_process_var(struct aco_type *type, const char *cat, struct ast_variable
ast_log(LOG_ERROR, "BUG! Somehow a config option for %s/%s was created with no handler!\n", cat, var->name); ast_log(LOG_ERROR, "BUG! Somehow a config option for %s/%s was created with no handler!\n", cat, var->name);
return -1; return -1;
} }
#ifdef AST_DEVMODE
if (opt->doc_unavailable) {
ast_log(LOG_ERROR, "Config option '%s' of type '%s' is not completely documented and can not be set\n", var->name, type->name);
return -1;
}
#endif
if (opt->handler(opt, var, obj)) { if (opt->handler(opt, var, obj)) {
ast_log(LOG_ERROR, "Error parsing %s=%s at line %d of %s\n", var->name, var->value, var->lineno, var->file); ast_log(LOG_ERROR, "Error parsing %s=%s at line %d of %s\n", var->name, var->value, var->lineno, var->file);
return -1; return -1;

Loading…
Cancel
Save