call ecore_init() in the CoreRuntime constructor.
[platform/core/dotnet/launcher.git] / NativeLauncher / launcher / dotnet / dotnet_launcher.cc
index c0b5300..e6d3bc7 100644 (file)
 
 
 #include <dlfcn.h>
+#include <signal.h>
 
 #include <string>
 #include <fstream>
 #include <vector>
+#include <sstream>
 
+#include <locale>
+#include <codecvt>
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <linux/limits.h>
+
+#include <storage.h>
+#include <vconf.h>
+#include <app_common.h>
+
+#include <Ecore.h>
+
+#include "injection.h"
 #include "utils.h"
 #include "log.h"
 #include "launcher.h"
 #include "dotnet_launcher.h"
+#include "plugin_manager.h"
+#include "path_manager.h"
+#include "log_manager.h"
+
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+static const char* __FRAMEWORK_DIR = __STR(FRAMEWORK_DIR);
+#undef __STR
+#undef __XSTR
 
 namespace tizen {
 namespace runtime {
 namespace dotnetcore {
 
-CoreRuntime::CoreRuntime() :
+#if defined (__aarch64__)
+#define ARCHITECTURE_IDENTIFIER "arm64"
+
+#elif defined (__arm__)
+#define ARCHITECTURE_IDENTIFIER "armel"
+
+#elif defined (__x86_64__)
+#define ARCHITECTURE_IDENTIFIER "x64"
+
+#elif defined (__i386__)
+#define ARCHITECTURE_IDENTIFIER "x86"
+
+#else
+#error "Unknown target"
+#endif
+
+static const char* __TIZEN_RID_VERSION_KEY = "db/dotnet/tizen_rid_version";
+
+// The sequence of RID_FALLBACK graphs must be:
+// 1. Tizen + Version + Architecture
+// 2. Tizen + Version
+// 3. OS(tizen, linux, unix) + Architecture
+// 4. OS(tizen, linux, unix)
+// 5. any, base
+static std::string getExtraNativeLibDirs(const std::string& appRoot)
+{
+       std::vector<std::string> RID_FALLBACK_GRAPH;
+       std::vector<std::string> RID_FALLBACK_TIZEN;
+       char* tizen_rid = vconf_get_str(__TIZEN_RID_VERSION_KEY);
+       if (tizen_rid) {
+               std::vector<std::string> version;
+               splitPath(tizen_rid, version);
+               std::reverse(std::begin(version), std::end(version));
+               for (unsigned int i = 0; i < version.size(); i++) {
+                       RID_FALLBACK_TIZEN.push_back(std::string("tizen." + version[i] + "-" + ARCHITECTURE_IDENTIFIER));
+                       RID_FALLBACK_TIZEN.push_back(std::string("tizen." + version[i]));
+               }
+               free(tizen_rid);
+       }
+
+       std::vector<std::string> RID_FALLBACK_OS = {"tizen", "linux", "unix"};
+       for (unsigned int i = 0; i < RID_FALLBACK_OS.size(); i++) {
+               RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i] + "-" +  ARCHITECTURE_IDENTIFIER));
+               RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i]));
+       }
+       RID_FALLBACK_GRAPH.push_back("any");
+       RID_FALLBACK_GRAPH.push_back("base");
+
+       std::string candidate;
+       for (unsigned int i = 0; i < RID_FALLBACK_GRAPH.size(); i++) {
+               if (!candidate.empty()) {
+                       candidate += ":";
+               }
+               candidate += concatPath(appRoot, "bin/runtimes/" + RID_FALLBACK_GRAPH[i] + "/native");
+       }
+
+       candidate = candidate + ":" + concatPath(appRoot, "lib/" ARCHITECTURE_IDENTIFIER);
+       if (!strncmp(ARCHITECTURE_IDENTIFIER, "arm64", 5)) {
+               candidate = candidate + ":" + concatPath(appRoot, "lib/aarch64");
+       } else if (!strncmp(ARCHITECTURE_IDENTIFIER, "armel", 5)) {
+               candidate = candidate + ":" + concatPath(appRoot, "lib/arm");
+       }
+
+       return candidate;
+}
+
+
+static std::vector<std::string> __envList;
+
+static void setEnvFromFile()
+{
+       std::string envList;
+       std::ifstream inFile(ENV_FILE_PATH);
+
+       __envList.clear();
+
+       if (inFile) {
+               _INFO("coreclr_env.list is found");
+
+               std::string token;
+               while (std::getline(inFile, token, '\n')) {
+                       if (!token.empty()) {
+                               __envList.push_back(token);
+                       }
+               }
+
+               for (unsigned int i = 0; i < __envList.size(); i++) {
+                       putenv(const_cast<char *>(__envList[i].c_str()));
+               }
+       } else {
+               _INFO("coreclr_env.list file is not found. skip");
+       }
+}
+
+#define _unused(x) ((void)(x))
+
+struct sigaction sig_abrt_new;
+struct sigaction sig_abrt_old;
+
+static bool checkOnSigabrt = false;
+static bool checkOnTerminate = false;
+
+static void onSigabrt(int signum)
+{
+       // use unused variable to avoid build warning
+       ssize_t ret = write(STDERR_FILENO, "onSigabrt called\n", 17);
+
+       if (checkOnTerminate) {
+               ret = write(STDERR_FILENO, "onSigabrt called while terminate. go to exit\n", 45);
+               _unused(ret);
+               exit(0);
+       }
+
+       if (checkOnSigabrt) {
+               ret = write(STDERR_FILENO, "onSigabrt called again. go to exit\n", 35);
+               _unused(ret);
+               exit(0);
+       }
+
+       checkOnSigabrt = true;
+       if (sigaction(SIGABRT, &sig_abrt_old, NULL) == 0) {
+               if (raise(signum) < 0) {
+                       ret = write(STDERR_FILENO, "Fail to raise SIGABRT\n", 22);
+               }
+       } else {
+               ret = write(STDERR_FILENO, "Fail to set original SIGABRT handler\n", 37);
+       }
+       _unused(ret);
+}
+
+static void registerSigHandler()
+{
+       sig_abrt_new.sa_handler = onSigabrt;
+       if (sigemptyset(&sig_abrt_new.sa_mask) != 0) {
+               _ERR("Fail to sigemptyset");
+       }
+
+       if (sigaction(SIGABRT, &sig_abrt_new, &sig_abrt_old) < 0) {
+               _ERR("Fail to add sig handler");
+       }
+}
+
+static bool storage_cb(int id, storage_type_e type, storage_state_e state, const char *path, void *user_data)
+{
+       int* tmp = (int*)user_data;
+       if (type == STORAGE_TYPE_INTERNAL)
+       {
+               *tmp = id;
+               return false;
+       }
+
+       return true;
+}
+
+static void initEnvForSpecialFolder()
+{
+       int storageId;
+       int error;
+       char *path = NULL;
+
+       error = storage_foreach_device_supported(storage_cb, &storageId);
+       if (error != STORAGE_ERROR_NONE) {
+               return;
+       }
+
+       error = storage_get_directory(storageId, STORAGE_DIRECTORY_IMAGES, &path);
+       if (error == STORAGE_ERROR_NONE && path != NULL) {
+               setenv("XDG_PICTURES_DIR", 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;
+       }
+
+       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;
+       }
+}
+
+void CoreRuntime::preloadTypes()
+{
+       const static std::string initDllPath = concatPath(__FRAMEWORK_DIR, "Tizen.Init.dll");
+       if (!isFileExist(initDllPath)) {
+               _ERR("Failed to locate Tizen.Init.dll");
+               return;
+       }
+
+       typedef void (*InitDelegate)();
+       InitDelegate initDelegate;
+
+       int ret = createDelegate(__hostHandle,
+               __domainId,
+               "Tizen.Init",
+               "Tizen.Init.TypeLoader",
+               "PreloadTypes",
+               (void**)&initDelegate);
+
+       if (ret < 0) {
+               _ERR("Failed to create delegate for PreloadTypes (0x%08x)", ret);
+       } else {
+               initDelegate();
+       }
+}
+
+CoreRuntime::CoreRuntime(const char* mode) :
        initializeClr(nullptr),
        executeAssembly(nullptr),
        shutdown(nullptr),
        createDelegate(nullptr),
+       setEnvironmentVariable(nullptr),
        __coreclrLib(nullptr),
        __hostHandle(nullptr),
        __domainId(-1),
-       preparedFunction(nullptr),
-       launchFunction(nullptr)
+       fd(0),
+       __initialized(false),
+       __isProfileMode(false)
 {
-#define __XSTR(x) #x
-#define __STR(x) __XSTR(x)
-
-#ifdef DEVICE_API_DIR
-       __deviceAPIDirectory = __STR(DEVICE_API_DIR);
-#endif
-#ifdef RUNTIME_DIR
-       __runtimeDirectory = __STR(RUNTIME_DIR);
-#endif
-#ifdef NATIVE_LIB_DIR
-       __nativeLibDirectory = __STR(NATIVE_LIB_DIR);
-#endif
+       _INFO("Constructor called!!");
 
-#ifdef USE_MANAGED_LAUNCHER
-#ifdef CORECLR_LAUNCHER_ASSEMBLY_PATH
-       __launcherAssembly = __STR(CORECLR_LAUNCHER_ASSEMBLY_PATH);
-#endif
-#endif
+       // Intiailize ecore first (signal handlers, etc.) before runtime init.
+       ecore_init();
 
-#undef __STR
-#undef __XSTR
+       char *env = nullptr;
+       env = getenv("CORECLR_ENABLE_PROFILING");
+       if (env != nullptr && !strcmp(env, "1")) {
+               _INFO("profiling mode on");
+               __isProfileMode = true;
+       }
 
-       _DBG("Constructor called!!");
+       // plugin initialize should be called before start loader mainloop.
+       // In case of VD plugins, attaching secure zone is done in the plugin_initialize().
+       // When attaching to a secure zone, if there is a created thread, it will failed.
+       // So, plugin initialize should be called before mainloop start.
+       if (initializePluginManager(mode) < 0) {
+               _ERR("Failed to initialize PluginManager");
+       }
 }
 
 CoreRuntime::~CoreRuntime()
 {
+       // workaround : to prevent crash while process terminate on profiling mode,
+       //              kill process immediately.
+       // see https://github.com/dotnet/coreclr/issues/26687
+       if (__isProfileMode) {
+               _INFO("shutdown process immediately.");
+               _exit(0);
+       }
+
        dispose();
 }
 
-int CoreRuntime::initialize(bool standalone)
+int CoreRuntime::initialize(bool standalone, bool useDlog)
 {
+       // checkInjection checks dotnet-launcher run mode
+       // At the moment, this mechanism is used only when the Memory Profiler is started.
+       int res = checkInjection();
+       if (res != 0) {
+               _ERR("Failed to initnialize Memory Profiler");
+               return -1;
+       }
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+
+#ifdef NATIVE_LIB_DIR
+       __nativeLibDirectory = __STR(NATIVE_LIB_DIR);
+#endif
+
+#undef __STR
+#undef __XSTR
+
 #ifdef __arm__
        // libunwind library is used to unwind stack frame, but libunwind for ARM
        // does not support ARM vfpv3/NEON registers in DWARF format correctly.
@@ -87,53 +350,41 @@ int CoreRuntime::initialize(bool standalone)
        putenv(const_cast<char *>("UNW_ARM_UNWIND_METHOD=6"));
 #endif // __arm__
 
-       if (standalone) {
-               const char *deviceApiDirectory = getenv("__deviceAPIDirectory");
-               const char *runtimeDirectory = getenv("__runtimeDirectory");
-               if (deviceApiDirectory != nullptr)
-                       __deviceAPIDirectory = deviceApiDirectory;
-               if (runtimeDirectory != nullptr)
-                       __runtimeDirectory = runtimeDirectory;
-
-#ifdef USE_MANAGED_LAUNCHER
-               const char *launcherAssembly = getenv("__launcherAssembly");
-               if (launcherAssembly != nullptr)
-                       __launcherAssembly = launcherAssembly;
-#endif
-       }
+       // Disable debug pipes and semaphores creation in case of non-standlone mode
+       if (!standalone)
+               putenv(const_cast<char *>("COMPlus_EnableDiagnostics=0"));
 
-       if (__deviceAPIDirectory.empty()) {
-               _ERR("Empty Device API Directory");
-               return 1;
-       } else {
-               __deviceAPIDirectory = absolutePath(__deviceAPIDirectory);
-       }
+       // Write Debug.WriteLine to stderr
+       putenv(const_cast<char *>("COMPlus_DebugWriteToStdErr=1"));
 
-       if (__runtimeDirectory.empty()) {
-               _ERR("Empty Runtime Directory");
-               return 1;
-       } else {
-               __runtimeDirectory = absolutePath(__runtimeDirectory);
-       }
+#ifdef USE_DEFAULT_BASE_ADDR
+       putenv(const_cast<char *>("COMPlus_UseDefaultBaseAddr=1"));
+#endif // USE_DEFAULT_BASE_ADDR
 
-#ifdef USE_MANAGED_LAUNCHER
-       if (__launcherAssembly.empty()) {
-               _ERR("Empty Launcher Assembly");
-               return 1;
-       } else {
-               __launcherAssembly = absolutePath(__launcherAssembly);
+       // read string from external file and set them to environment value.
+       setEnvFromFile();
+
+       if (initializePathManager(std::string(), std::string(), std::string()) < 0) {
+               _ERR("Failed to initialize PathManager");
+               return -1;
        }
-#endif
 
-       std::string libCoreclr(concatPath(__runtimeDirectory, "libcoreclr.so"));
+       if (useDlog && !pluginHasLogControl()) {
+               if (initializeLogManager() < 0) {
+                       _ERR("Failed to initnialize LogManager");
+                       return -1;
+               }
+       }
 
-       _DBG("libcoreclr : %s", libCoreclr.c_str());
+       std::string libCoreclr(concatPath(getRuntimeDir(), "libcoreclr.so"));
 
        __coreclrLib = dlopen(libCoreclr.c_str(), RTLD_NOW | RTLD_LOCAL);
        if (__coreclrLib == nullptr) {
                char *err = dlerror();
                _ERR("dlopen failed to open libcoreclr.so with error %s", err);
-               return 1;
+               if (access(libCoreclr.c_str(), R_OK) == -1)
+                       _ERR("access '%s': %s\n", libCoreclr.c_str(), strerror(errno));
+               return -1;
        }
 
 #define CORELIB_RETURN_IF_NOSYM(type, variable, name) \
@@ -141,7 +392,7 @@ int CoreRuntime::initialize(bool standalone)
                variable = (type)dlsym(__coreclrLib, name); \
                if (variable == nullptr) { \
                        _ERR(name " is not found in the libcoreclr.so"); \
-                       return 1; \
+                       return -1; \
                } \
        } while (0)
 
@@ -152,15 +403,55 @@ int CoreRuntime::initialize(bool standalone)
 
 #undef CORELIB_RETURN_IF_NOSYM
 
-       _DBG("libcoreclr dlopen and dlsym success");
-       _DBG("this addr : %x", this);
-       _DBG("coreclr_initialize : %x", initializeClr);
+       _INFO("libcoreclr dlopen and dlsym success");
+
+       if (!standalone) {
+               pluginPreload();
+       }
+
+       // Set environment for System.Environment.SpecialFolder
+       // Below function creates dbus connection by callging storage API.
+       // If dbus connection is created bofere fork(), forked process cannot use dbus.
+       // To avoid gdbus blocking issue, below function should be called after fork()
+       initEnvForSpecialFolder();
+
+       fd = open("/proc/self", O_DIRECTORY);
+       std::string appRoot = std::string("/proc/self/fd/") + std::to_string(fd);
+       std::string appBin = concatPath(appRoot, "bin");
+       std::string appLib = concatPath(appRoot, "lib");
+       std::string appTac = concatPath(appBin, TAC_SYMLINK_SUB_DIR);
+       std::string probePath = appBin + ":" + appLib + ":" + appTac;
+       std::string NIprobePath = concatPath(appBin, APP_NI_SUB_DIR) + ":" + concatPath(appLib, APP_NI_SUB_DIR) + ":" + appTac;
+       std::string tpa = getTPA();
+       std::string runtimeDir = getRuntimeDir();
+       std::string nativeLibPath = getExtraNativeLibDirs(appRoot) + ":" + appBin + ":" + appLib + ":" + __nativeLibDirectory + ":" + runtimeDir;
+       std::string appName = std::string("dotnet-launcher-") + std::to_string(getpid());
+
+       if (!initializeCoreClr(appName.c_str(), probePath.c_str(), NIprobePath.c_str(), nativeLibPath.c_str(), tpa.c_str())) {
+               _ERR("Failed to initialize coreclr");
+               return -1;
+       }
+
+       int st = createDelegate(__hostHandle, __domainId, "Dotnet.Launcher", "Dotnet.Launcher.Environment", "SetEnvironmentVariable", (void**)&setEnvironmentVariable);
+       if (st < 0 || setEnvironmentVariable == nullptr) {
+               _ERR("Create delegate for Dotnet.Launcher.dll -> Dotnet.Launcher.Environment -> SetEnvironmentVariable failed (0x%08x)", st);
+               return -1;
+       }
+
+       __initialized = true;
+
+       if (!standalone) {
+               preloadTypes();         // Preload common managed code
+       }
+
+       _INFO("CoreRuntime initialize success");
 
        return 0;
 }
 
 bool CoreRuntime::initializeCoreClr(const char* appId,
                                                                         const char* assemblyProbePaths,
+                                                                        const char* NIProbePaths,
                                                                         const char* pinvokeProbePaths,
                                                                         const char* tpaList)
 {
@@ -175,7 +466,7 @@ bool CoreRuntime::initializeCoreClr(const char* appId,
        const char *propertyValues[] = {
                tpaList,
                assemblyProbePaths,
-               assemblyProbePaths,
+               NIProbePaths,
                pinvokeProbePaths,
                "UseLatestBehaviorWhenTFMNotSpecified"
        };
@@ -195,126 +486,98 @@ bool CoreRuntime::initializeCoreClr(const char* appId,
                return false;
        }
 
-       _DBG("Initialize core clr success");
+       pluginSetCoreclrInfo(__hostHandle, __domainId, createDelegate);
+
+       _INFO("Initialize core clr success");
        return true;
 }
 
-int CoreRuntime::runManagedLauncher(const char* appId, const char* appBase, const char* tpaList)
+void CoreRuntime::dispose()
 {
-       if (fileNotExist(__launcherAssembly)) {
-               _ERR("Launcher assembly is not exist in %s", __launcherAssembly.c_str());
-               return 1;
-       }
+       // call plugin finalize function to notify finalize to plugin
+       // dlclose shoud be done after coreclr shutdown to avoid breaking signal chain
+       pluginFinalize();
 
-       if (!initializeCoreClr(appId, appBase, appBase, tpaList)) {
-               _ERR("Failed to initialize coreclr");
-               return 1;
-       }
-
-#ifdef USE_MANAGED_LAUNCHER
-       void *preparedFunctionDelegate;
-       int st = createDelegate(__hostHandle, __domainId,
-                                                       "Tizen.Runtime",
-                                                       "Tizen.Runtime.Coreclr.AssemblyManager",
-                                                       "Prepared", &preparedFunctionDelegate);
-       if (st < 0) {
-               _ERR("Create delegate for Launch prepared function is fail (0x%08x)", st);
-               return 1;
-       }
-       preparedFunction = reinterpret_cast<PreparedFunctionPtr>(preparedFunctionDelegate);
-
-       if (preparedFunction != nullptr)
-               preparedFunction();
-
-       void *launchFunctionDelegate;
-       st = createDelegate(__hostHandle, __domainId,
-                                               "Tizen.Runtime",
-                                               "Tizen.Runtime.Coreclr.AssemblyManager",
-                                               "Launch", &launchFunctionDelegate);
-       if (st < 0) {
-               _ERR("Create delegate for Launch managed function is fail! (0x%08x)", st);
-               return 1;
-       }
-       launchFunction = reinterpret_cast<LaunchFunctionPtr>(launchFunctionDelegate);
-#endif
-       return 0;
-}
+       // ignore the signal generated by an exception that occurred during shutdown
+       checkOnTerminate = true;
 
-void CoreRuntime::dispose()
-{
        if (__hostHandle != nullptr) {
                int st = shutdown(__hostHandle, __domainId);
                if (st < 0)
                        _ERR("shutdown core clr fail! (0x%08x)", st);
+               __hostHandle = nullptr;
        }
 
-       if (dlclose(__coreclrLib) != 0)
-               _ERR("libcoreclr.so close failed");
+       if (__coreclrLib != nullptr) {
+               if (dlclose(__coreclrLib) != 0) {
+                       _ERR("libcoreclr.so close failed");
+               }
+
+               __coreclrLib = nullptr;
+       }
 
-       __coreclrLib = nullptr;
+       finalizePluginManager();
+       finalizePathManager();
 
-       _DBG("Dotnet runtime disposed");
+       __envList.clear();
+
+       _INFO("Dotnet runtime disposed");
 }
 
 int CoreRuntime::launch(const char* appId, const char* root, const char* path, int argc, char* argv[])
 {
+       if (!__initialized) {
+               _ERR("Runtime is not initialized");
+               return -1;
+       }
+
        if (path == nullptr) {
                _ERR("executable path is null");
-               return 1;
+               return -1;
        }
 
-       if (fileNotExist(path)) {
+       if (!isFileExist(path)) {
                _ERR("File not exist : %s", path);
-               return 1;
+               return -1;
        }
 
-       std::string tpa;
-       std::string appRoot = root;
-       std::string appBin = concatPath(appRoot, "bin");
-       std::string appLib = concatPath(appRoot, "lib");
-       std::string probePath = appBin + ":" + appLib + ":" + __nativeLibDirectory;
-
-       std::vector<std::string> searchDirectories;
-       searchDirectories.push_back(appBin);
-       searchDirectories.push_back(appLib);
-       searchDirectories.push_back(__runtimeDirectory);
-       searchDirectories.push_back(__deviceAPIDirectory);
-#ifdef USE_MANAGED_LAUNCHER
-       searchDirectories.push_back(baseName(__launcherAssembly));
-#endif
-
-       assembliesInDirectory(searchDirectories, tpa);
+       // launchpad override stdout and stderr to journalctl before launch application.
+       // we have to re-override that to input pipe for logging thread.
+       // if LogManager is not initialized, below redirectFD will return 0;
+       if (redirectFD() < 0) {
+               _ERR("Failed to redirect FD");
+               return -1;
+       }
 
-#ifdef USE_MANAGED_LAUNCHER
-       runManagedLauncher(appId, probePath.c_str(), tpa.c_str());
+       // VD has their own signal handler.
+       if (!pluginHasLogControl()) {
+               registerSigHandler();
+       }
 
-       bool success = false;
-       if (launchFunction != nullptr) {
-               std::string cppPath(path);
+       pluginSetAppInfo(appId, path);
 
-               if (isManagedAssembly(cppPath) && !isNativeImage(cppPath)) {
-                       size_t extindex = cppPath.size() - 4;
-                       cppPath = cppPath.substr(0, extindex) + ".ni" + cppPath.substr(extindex, 4);
-                       if (!fileNotExist(cppPath))
-                               path = cppPath.c_str();
-               }
+       int fd2 = open(root, O_DIRECTORY);
+       dup3(fd2, fd, O_CLOEXEC);
+       if (fd2 >= 0)
+               close(fd2);
 
-               success = launchFunction(root, path, argc, argv);
-               if (!success)
-                       _ERR("Failed to launch Application %s", path);
-               return success ? 0 : 1;
-       } else {
-               _ERR("Failed to find launch function");
-               return 1;
+       // set application data path to coreclr environment.
+       // application data path can be changed by owner. So, we have to set data path just before launching.
+       char* localDataPath = app_get_data_path();
+       if (localDataPath != nullptr) {
+               setEnvironmentVariable("XDG_DATA_HOME", localDataPath);
+               free(localDataPath);
        }
-#else
-       int st = initializeCoreClr(appId, probePath.c_str(), probePath.c_str(), tpa.c_str());
+
+       pluginBeforeExecute();
+
+       _INFO("execute assembly : %s", path);
+
        unsigned int ret = 0;
-       st = executeAssembly(__hostHandle, __domainId, argc, (const char**)argv, path, &ret);
+       int st = executeAssembly(__hostHandle, __domainId, argc, (const char**)argv, path, &ret);
        if (st < 0)
                _ERR("Failed to Execute Assembly %s (0x%08x)", path, st);
        return ret;
-#endif
 }
 
 }  // namespace dotnetcore