Add log for profile data when the app runs
[platform/core/dotnet/launcher.git] / NativeLauncher / launcher / lib / core_runtime.cc
index f78dd54..ee23fde 100644 (file)
@@ -56,6 +56,8 @@ static coreclr_execute_assembly_ptr executeAssembly = nullptr;
 static coreclr_shutdown_ptr shutdown = nullptr;
 static coreclr_create_delegate_ptr createDelegate = nullptr;
 static set_environment_variable_ptr setEnvironmentVariable = nullptr;
+static stop_profile_after_delay_ptr stopProfileAfterDelay = nullptr;
+static set_switch_ptr setSwitch = nullptr;
 static void* __coreclrLib = nullptr;
 static void* __hostHandle = nullptr;
 static unsigned int __domainId = -1;
@@ -63,6 +65,8 @@ static bool __initialized = false;
 static bool __isProfileMode = false;
 PathManager* CoreRuntime::__pm = nullptr;
 
+#define MAX_DELAY_SEC 100
+
 static std::vector<std::string> __envList;
 
 static void setEnvFromFile()
@@ -150,36 +154,38 @@ static bool storage_cb(int id, storage_type_e type, storage_state_e state, const
        return true;
 }
 
-static void initEnvForSpecialFolder()
+static void setSpecialFolder(storage_directory_e type, const char* key)
 {
-       int storageId;
        int error;
-       char *path = NULL;
+       char* path = NULL;
+       static int __storageId = -1;
 
-       error = storage_foreach_device_supported(storage_cb, &storageId);
-       if (error != STORAGE_ERROR_NONE) {
-               return;
+       if (__storageId < 0) {
+               error = storage_foreach_device_supported(storage_cb, &__storageId);
+               if (error != STORAGE_ERROR_NONE) {
+                       return;
+               }
        }
 
-       error = storage_get_directory(storageId, STORAGE_DIRECTORY_IMAGES, &path);
+       error = storage_get_directory(__storageId, type, &path);
        if (error == STORAGE_ERROR_NONE && path != NULL) {
-               setenv("XDG_PICTURES_DIR", const_cast<char *>(path), 1);
+               setenv(key, const_cast<char *>(path), 1);
                free(path);
-               path = NULL;
        }
+}
 
-       error = storage_get_directory(storageId, STORAGE_DIRECTORY_MUSIC, &path);
-       if (error == STORAGE_ERROR_NONE && path != NULL) {
-               setenv("XDG_MUSIC_DIR", const_cast<char *>(path), 1);
-               free(path);
-               path = NULL;
+static void initEnvForSpecialFolder()
+{
+       if (getenv("XDG_PICTURES_DIR") == NULL) {
+               setSpecialFolder(STORAGE_DIRECTORY_IMAGES, "XDG_PICTURES_DIR");
        }
 
-       error = storage_get_directory(storageId, STORAGE_DIRECTORY_VIDEOS, &path);
-       if (error == STORAGE_ERROR_NONE && path != NULL) {
-               setenv("XDG_VIDEOS_DIR", const_cast<char *>(path), 1);
-               free(path);
-               path = NULL;
+       if (getenv("XDG_MUSIC_DIR") == NULL) {
+               setSpecialFolder(STORAGE_DIRECTORY_MUSIC, "XDG_MUSIC_DIR");
+       }
+
+       if (getenv("XDG_VIDEOS_DIR") == NULL) {
+               setSpecialFolder(STORAGE_DIRECTORY_VIDEOS, "XDG_VIDEOS_DIR");
        }
 }
 
@@ -271,12 +277,15 @@ void preload()
 
 bool initializeCoreClr(PathManager* pm, const std::string& tpa)
 {
+       bool ncdbStartupHook = isNCDBStartupHookProvided();
+
        const char *propertyKeys[] = {
                "TRUSTED_PLATFORM_ASSEMBLIES",
                "APP_PATHS",
                "APP_NI_PATHS",
                "NATIVE_DLL_SEARCH_DIRECTORIES",
-               "AppDomainCompatSwitch"
+               "AppDomainCompatSwitch",
+               ncdbStartupHook ? "STARTUP_HOOKS" : "" // must be the last one
        };
 
        const char *propertyValues[] = {
@@ -284,14 +293,15 @@ bool initializeCoreClr(PathManager* pm, const std::string& tpa)
                pm->getAppPaths().c_str(),
                pm->getAppNIPaths().c_str(),
                pm->getNativeDllSearchingPaths().c_str(),
-               "UseLatestBehaviorWhenTFMNotSpecified"
+               "UseLatestBehaviorWhenTFMNotSpecified",
+               ncdbStartupHook ? getNCDBStartupHook() : "" // must be the last one
        };
 
        std::string selfPath = readSelfPath();
 
        int st = initializeClr(selfPath.c_str(),
                                                        "TizenDotnetApp",
-                                                       sizeof(propertyKeys) / sizeof(propertyKeys[0]),
+                                                       sizeof(propertyKeys) / sizeof(propertyKeys[0]) - (ncdbStartupHook ? 0 : 1),
                                                        propertyKeys,
                                                        propertyValues,
                                                        &__hostHandle,
@@ -369,6 +379,9 @@ int CoreRuntime::initialize(const char* appType, LaunchMode launchMode)
        putenv(const_cast<char *>("COMPlus_UseDefaultBaseAddr=1"));
 #endif // USE_DEFAULT_BASE_ADDR
 
+       // Disable config cache to set environment after coreclr_initialize()
+       putenv(const_cast<char *>("COMPlus_DisableConfigCache=1"));
+
        // read string from external file and set them to environment value.
        setEnvFromFile();
 
@@ -389,6 +402,11 @@ int CoreRuntime::initialize(const char* appType, LaunchMode launchMode)
                __pm->addNativeDllSearchingPaths(pluginNativePaths, true);
        }
 
+       char* pluginExtraDllPaths = pluginGetExtraDllPath();
+       if (pluginExtraDllPaths && pluginExtraDllPaths[0] != '\0') {
+               __pm->setExtraDllPaths(pluginExtraDllPaths);
+       }
+
        pluginHasLogControl();
 
        std::string libCoreclr(concatPath(__pm->getRuntimePath(), "libcoreclr.so"));
@@ -443,6 +461,18 @@ int CoreRuntime::initialize(const char* appType, LaunchMode launchMode)
                return -1;
        }
 
+       st = createDelegate(__hostHandle, __domainId, "Tizen.Runtime", "Tizen.Runtime.Profiler", "StopProfileAfterDelay", (void**)&stopProfileAfterDelay);
+       if (st < 0 || stopProfileAfterDelay == nullptr) {
+               _ERR("Create delegate for Tizen.Runtime.dll -> Tizen.Runtime.Profiler -> StopProfileAfterDelay failed (0x%08x)", st);
+               return -1;
+       }
+
+       st = createDelegate(__hostHandle, __domainId, "Tizen.Runtime", "Tizen.Runtime.AppSetting", "SetSwitch", (void**)&setSwitch);
+       if (st < 0 || setSwitch == nullptr) {
+               _ERR("Create delegate for Tizen.Runtime.dll -> Tizen.Runtime.AppSetting -> SetSwitch failed (0x%08x)", st);
+               return -1;
+       }
+
        if (launchMode == LaunchMode::loader) {
                // terminate candidate process if language is changed.
                // CurrentCulture created for preloaded dlls should be updated.
@@ -549,13 +579,34 @@ int CoreRuntime::launch(const char* appId, const char* root, const char* path, i
 
                        setEnvironmentVariable("COMPlus_MultiCoreJitProfile", multiCoreJitProfile);
                        setEnvironmentVariable("COMPlus_MultiCoreJitMinNumCpus", "1");
+
                        if (exist(multiCoreJitProfile)) {
                                setEnvironmentVariable("COMPlus_MultiCoreJitNoProfileGather", "1");
+                               _INFO("Completed loading of profile data for the %s", appId);
+                       } else {
+                               setEnvironmentVariable("COMPlus_MultiCoreJitNoProfileGather", "0");
+                               // stop profiling and write collected data after delay if env value is set.
+                               char *env = getenv("CLR_MCJ_PROFILE_WRITE_DELAY");
+                               if (env != nullptr) {
+                                       int delay = std::atoi(env);
+                                       // To avoid undefined behavior by out-of-range input(atoi), set max delay value to 100.
+                                       if (delay > 0) {
+                                               if (delay > MAX_DELAY_SEC) delay = MAX_DELAY_SEC;
+                                               stopProfileAfterDelay(delay);
+                                       }
+                               }
+                               _INFO("Create the profile data for the %s", appId);
                        }
                }
                free(localDataPath);
        }
 
+       if (exist(__pm->getAppRootPath() + "/bin/" + DISABLE_IPV6_FILE)) {
+               setSwitch("System.Net.DisableIPv6", true);
+       }
+
+       setSwitch("Switch.System.Diagnostics.StackTrace.ShowILOffsets", true);
+
        vconf_ignore_key_changed(VCONFKEY_LANGSET, langChangedCB);
 
        pluginBeforeExecute();