} else {
// Output all
f->open_array_section("options");
- for (const auto &option : ceph_options) {
+ for (const auto &option : get_ceph_options()) {
f->dump_object("option", option);
}
f->close_section();
{
// Load the compile-time list of Option into
// a map so that we can resolve keys quickly.
- for (const auto &i : ceph_options) {
+ for (const auto &i : get_ceph_options()) {
if (schema.count(i.name)) {
// We may be instantiated pre-logging so send
std::cerr << "Duplicate config key in schema: '" << i.name << "'"
}
}
-const std::vector<Option> ceph_options = build_options();
+const std::vector<Option>& get_ceph_options() {
+ // Use a static pointer that's never destroyed to avoid use-after-free
+ // when background threads access options during program exit
+ static const std::vector<Option>* options = new std::vector<Option>(build_options());
+ return *options;
+}
return n << 40;
}
-extern const std::vector<Option> ceph_options;
+const std::vector<Option>& get_ceph_options();
unique_ptr<Formatter> f{Formatter::create(format, "json-pretty", "json-pretty")};
// Output all
f->open_array_section("options");
- for (const auto &option : ceph_options) {
+ for (const auto &option : get_ceph_options()) {
f->dump_object("option", option);
}
f->close_section();
if (f) {
f->open_array_section("options");
}
- for (auto& i : ceph_options) {
+ for (auto& i : get_ceph_options()) {
if (f) {
f->dump_string("option", i.name);
} else {