@@ -51,45 +51,82 @@ std::filesystem::path get_helper_path()
51
51
52
52
namespace dds {
53
53
54
- const std::string &engine_settings::default_rules_file ()
55
- {
56
- struct def_rules_file {
57
- def_rules_file ()
58
- {
59
- std::filesystem::path base_path;
54
+ namespace {
55
+ struct def_rules_file {
56
+ std::atomic<std::string *> stored_file{};
57
+
58
+ def_rules_file () = default ;
59
+ def_rules_file (const def_rules_file &) = delete ;
60
+ def_rules_file (def_rules_file &&) = delete ;
61
+ def_rules_file &operator =(const def_rules_file &) = delete ;
62
+ def_rules_file &operator =(def_rules_file &&) = delete ;
63
+
64
+ const std::string &get ()
65
+ {
66
+ auto *cur_val = stored_file.load ();
67
+ if (cur_val == nullptr ) {
68
+ auto *new_val = initialize ().release ();
69
+ if (!stored_file.compare_exchange_strong (cur_val, new_val)) {
70
+ delete new_val; // NOLINT
71
+ // cur_val is now the currently stored value
72
+ } else {
73
+ cur_val = new_val;
74
+ }
75
+ }
76
+ return *cur_val;
77
+ }
78
+
79
+ static std::unique_ptr<std::string> initialize ()
80
+ {
81
+ std::filesystem::path base_path;
82
+ std::unique_ptr<std::string> file;
60
83
84
+ try {
85
+ base_path = get_helper_path ().parent_path ();
86
+ } catch (const std::exception &e) {
87
+ file = std::make_unique<std::string>(
88
+ " <error resolving helper library path: " +
89
+ std::string (e.what ()) + " >" );
90
+
91
+ // try relative to the executable instead
61
92
try {
62
- base_path = get_helper_path ().parent_path ();
63
- } catch (const std::exception &e) {
64
- file = " <error resolving helper library path: " +
65
- std::string (e.what ()) + " >" ;
66
-
67
- // try relative to the executable instead
68
- try {
69
- auto psp = std::filesystem::path{" /proc/self/exe" };
70
- if (std::filesystem::is_symlink (psp)) {
71
- psp = std::filesystem::read_symlink (psp);
72
- }
73
- base_path = psp.parent_path ();
74
- } catch (const std::exception &e) {
75
- file =
76
- " <error resolving both library and executable path: " +
77
- std::string (e.what ()) + " >" ;
78
- return ;
93
+ auto psp = std::filesystem::path{" /proc/self/exe" };
94
+ if (std::filesystem::is_symlink (psp)) {
95
+ psp = std::filesystem::read_symlink (psp);
79
96
}
97
+ base_path = psp.parent_path ();
98
+ } catch (const std::exception &e) {
99
+ file = std::make_unique<std::string>(
100
+ " <error resolving both library and executable path: " +
101
+ std::string (e.what ()) + " >" );
102
+ return file;
80
103
}
104
+ }
81
105
82
- file = base_path / " ../etc/recommended.json" ;
83
- if (!std::filesystem::exists (file)) {
84
- // This fallback file is set by a custom/old installer on
85
- // appsec repository
86
- file = base_path / " ../etc/dd-appsec/recommended.json" ;
87
- }
106
+ file = std::make_unique<std::string>(
107
+ base_path / " ../etc/recommended.json" );
108
+ if (!std::filesystem::exists (*file)) {
109
+ // This fallback file is set by a custom/old installer on
110
+ // appsec repository
111
+ file = std::make_unique<std::string>(
112
+ base_path / " ../etc/dd-appsec/recommended.json" );
88
113
}
89
- std::string file;
90
- };
91
114
92
- static def_rules_file const drf; // NOLINT
93
- return drf.file ;
94
- }
115
+ return file;
116
+ }
117
+
118
+ ~def_rules_file ()
119
+ {
120
+ auto *val = stored_file.load ();
121
+ delete val; // NOLINT
122
+ stored_file.store (nullptr );
123
+ }
124
+ };
125
+
126
+ // can't be a local static inside default_rules_file() because those
127
+ // register their atexit() handlers lazily, which is too late for us.
128
+ def_rules_file drf{}; // NOLINT
129
+ } // namespace
130
+
131
+ const std::string &engine_settings::default_rules_file () { return drf.get (); }
95
132
} // namespace dds
0 commit comments