Add SetSwitch API to Tizen.Runtime
[platform/core/dotnet/launcher.git] / NativeLauncher / launcher / lib / core_runtime.cc
index 13efc05..b9e75ac 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()
@@ -443,6 +447,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.
@@ -544,11 +560,23 @@ int CoreRuntime::launch(const char* appId, const char* root, const char* path, i
                // set profile.data path and collect/use it if it non-exists/exists.
                if (profile) {
                        char multiCoreJitProfile[strlen(localDataPath) + strlen(PROFILE_BASENAME) + 1];
-                       strncpy(multiCoreJitProfile, localDataPath, strlen(localDataPath) + 1);
+                       memcpy(multiCoreJitProfile, localDataPath, strlen(localDataPath) + 1);
                        strncat(multiCoreJitProfile, PROFILE_BASENAME, strlen(PROFILE_BASENAME));
 
                        setEnvironmentVariable("COMPlus_MultiCoreJitProfile", multiCoreJitProfile);
                        setEnvironmentVariable("COMPlus_MultiCoreJitMinNumCpus", "1");
+
+                       // 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);
+                               }
+                       }
+
                        if (exist(multiCoreJitProfile)) {
                                setEnvironmentVariable("COMPlus_MultiCoreJitNoProfileGather", "1");
                        }
@@ -556,6 +584,8 @@ int CoreRuntime::launch(const char* appId, const char* root, const char* path, i
                free(localDataPath);
        }
 
+       setSwitch("Switch.System.Diagnostics.StackTrace.ShowILOffsets", true);
+
        vconf_ignore_key_changed(VCONFKEY_LANGSET, langChangedCB);
 
        pluginBeforeExecute();