Set environment (LANG, LC_MESSAGE, LC_ALL) before using ICU API. accepted/tizen/unified/20200402.155646 submit/tizen/20200401.004644
authorWoongsuk Cho <ws77.cho@samsung.com>
Tue, 31 Mar 2020 03:38:39 +0000 (12:38 +0900)
committer이형주/Common Platform Lab(SR)/Staff Engineer/삼성전자 <leee.lee@samsung.com>
Wed, 1 Apr 2020 00:37:36 +0000 (09:37 +0900)
In order to operate ICU (used for globalization) normally, "LANG" and "LC_ALL" environment variables must be set before using ICU API.
In case of application running, AppFW set that variable. But when preloading the dll in the candidate process,
those environment variables are not set.
As a result, CultureInfo is incorrectly generated and malfunctions.
For example, uloc_getDefault() returns en_US_POSIX, CultureInfo is set to invariant mode.

Additionally, to apply language setting from native to managed, terminate and recreate candidate process when system language setting is changed.

After applying this patches, launching performance is reduced by 15ms ~ 20ms.
That is because previous .net application is launched in invariant mode.
(In invariant mode, string-related operations are fast.)

NativeLauncher/launcher/dotnet/dotnet_launcher.cc

index 890e5b7..650d5b7 100644 (file)
@@ -245,6 +245,35 @@ static void initEnvForSpecialFolder()
        }
 }
 
+// terminate candidate process when language changed
+// icu related data (CultureInfo, etc) should be recreated.
+static void langChangedCB(keynode_t *key, void* data)
+{
+       _INFO("terminiate candidate process to update language.");
+       exit(0);
+}
+
+static void setLang()
+{
+       char* lang = vconf_get_str(VCONFKEY_LANGSET);
+       if (!lang) {
+               _ERR("Fail to get language from vconf");
+               return;
+       }
+
+       // In order to operate ICU (used for globalization) normally, the following
+       // environment variables must be set before using ICU API.
+       // When running Applicaiton, the following environment variables are set by AppFW.
+       // But when preloading the dll in the candidate process, the following environment variables are not set
+       // As a result, CultureInfo is incorrectly generated and malfunctions.
+       // For example, uloc_getDefault() returns en_US_POSIX, CultureInfo is set to invariant mode.
+       setenv("LANG", const_cast<char *>(lang), 1);
+       setenv("LC_MESSAGES", const_cast<char *>(lang), 1);
+       setenv("LC_ALL", const_cast<char *>(lang), 1);
+
+       free(lang);
+}
+
 void CoreRuntime::preloadTypes()
 {
        const static std::string initDllPath = concatPath(__FRAMEWORK_DIR, "Tizen.Init.dll");
@@ -288,6 +317,9 @@ CoreRuntime::CoreRuntime(const char* mode) :
        // Intiailize ecore first (signal handlers, etc.) before runtime init.
        ecore_init();
 
+       // set language environment to support ICU
+       setLang();
+
        char *env = nullptr;
        env = getenv("CORECLR_ENABLE_PROFILING");
        if (env != nullptr && !strcmp(env, "1")) {
@@ -407,6 +439,10 @@ int CoreRuntime::initialize(bool standalone, bool useDlog, const char* corerunRo
 
        if (!standalone) {
                pluginPreload();
+
+               // terminate candidate process if language is changed.
+               // CurrentCulture created for preloaded dlls should be updated.
+               vconf_notify_key_changed(VCONFKEY_LANGSET, langChangedCB, NULL);
        }
 
        // Set environment for System.Environment.SpecialFolder
@@ -586,6 +622,8 @@ int CoreRuntime::launch(const char* appId, const char* root, const char* path, i
                free(localDataPath);
        }
 
+       vconf_ignore_key_changed(VCONFKEY_LANGSET, langChangedCB);
+
        pluginBeforeExecute();
 
        _INFO("execute assembly : %s", path);