[Fix] Resolve static init order fiasco
authorJihoon Lee <jhoon.it.lee@samsung.com>
Wed, 27 Jan 2021 01:15:12 +0000 (10:15 +0900)
committerJijoong Moon <jijoong.moon@samsung.com>
Mon, 1 Feb 2021 08:00:45 +0000 (17:00 +0900)
As static initialization order out of a translation unit is undefined,
initializing global caused some undefined behavior.

Initializing global app context is delayed until it is first called.

See https://gcc.gnu.org/legacy-ml/gcc-patches/2017-03/msg00863.html

Resolves #893

**Self evaluation:**
1. Build test: [X]Passed [ ]Failed [ ]Skipped
2. Run test: [X]Passed [ ]Failed [ ]Skipped

Signed-off-by: Jihoon Lee <jhoon.it.lee@samsung.com>
nntrainer/app_context.cpp

index 9fddb97..d3ef567 100644 (file)
@@ -49,22 +49,18 @@ namespace nntrainer {
 std::mutex factory_mutex;
 
 /**
- * @brief initiate global context
- *
- */
-static void init_global_context_nntrainer(void) __attribute__((constructor));
-
-/**
  * @brief finialize global context
  *
  */
 static void fini_global_context_nntrainer(void) __attribute__((destructor));
 
-static void init_global_context_nntrainer(void) {
+static void fini_global_context_nntrainer(void) {}
+
+std::once_flag global_app_context_init_flag;
+
+static void add_default_object(AppContext &ac) {
   /// @note all layers should be added to the app_context to gaurantee that
   /// createLayer/createOptimizer class is created
-  auto &ac = AppContext::Global();
-
   using OptType = ml::train::OptimizerType;
   ac.registerFactory(ml::train::createOptimizer<SGD>, SGD::type, OptType::SGD);
   ac.registerFactory(ml::train::createOptimizer<Adam>, Adam::type,
@@ -108,10 +104,9 @@ static void init_global_context_nntrainer(void) {
                      LayerType::LAYER_UNKNOWN);
 }
 
-static void fini_global_context_nntrainer(void) {}
-
 AppContext &AppContext::Global() {
   static AppContext instance;
+  std::call_once(global_app_context_init_flag, add_default_object, instance);
   return instance;
 }