Refactoring CoreRuntime and plugin (#247) accepted/tizen/unified/20200630.131320 submit/tizen/20200629.221257
author조웅석/Common Platform Lab(SR)/Principal Engineer/삼성전자 <ws77.cho@samsung.com>
Mon, 29 Jun 2020 21:52:56 +0000 (06:52 +0900)
committer이형주/Common Platform Lab(SR)/Staff Engineer/삼성전자 <leee.lee@samsung.com>
Mon, 29 Jun 2020 21:52:56 +0000 (06:52 +0900)
* Pass apptype to plugin insteadof mode

The meaning of the mode that is delivered during plugin initialization is not clear.
And, VD plugin use mode to distinguish app-type.

So, change the parameter of plugin_initialize from mode to apptype.
Also, the script was modified to obtain the apptype in the candidate process.

The parameter of the CoreRuntime constructor was also unnecessary and deleted.

* Change CoreRuntime to static class

CoreRuntime is a wrapper class of .NET Runtime (coreclr),
So, that cannot be created with multiple instance, and cannot be called
multiple times.

So, I changed CoreRuntime to static class which contains only static functions.
Also, it was changed to explicitly call what was called as a destructor.

Additionally, some function name and file name have been changed.

12 files changed:
NativeLauncher/CMakeLists.txt
NativeLauncher/dotnet.launcher
NativeLauncher/dotnet.loader
NativeLauncher/hydra/hydra_main.cc
NativeLauncher/inc/plugin_manager.h
NativeLauncher/launcher/exec/launcher.cc
NativeLauncher/launcher/exec/loader.cc
NativeLauncher/launcher/lib/core_runtime.cc [new file with mode: 0644]
NativeLauncher/launcher/lib/core_runtime.h [new file with mode: 0644]
NativeLauncher/launcher/lib/dotnet_launcher.cc [deleted file]
NativeLauncher/launcher/lib/dotnet_launcher.h [deleted file]
NativeLauncher/util/plugin_manager.cc

index 773686c229cdef957a90856b96fe1c1fca69c71e..1252576d59710c1a6439a51c980e632f2ea9ea37 100644 (file)
@@ -117,7 +117,7 @@ TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER_UTIL} ${${PROJECT_NAME}_LDFLAGS} "-ldl"
 SET(DOTNET_LAUNCHER_CORE "dotnet_launcher_core")
 SET(${DOTNET_LAUNCHER_CORE}_SOURCE_FILES
     launcher/lib/injection.cc
-    launcher/lib/dotnet_launcher.cc
+    launcher/lib/core_runtime.cc
 )
 ADD_LIBRARY(${DOTNET_LAUNCHER_CORE} SHARED ${${DOTNET_LAUNCHER_CORE}_SOURCE_FILES})
 SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER_CORE} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_LIB})
index 0cd09a21cd4707e3ab8f9763879d9721648af06f..4bcd42dacd87aab83c1aa460a79a64904a7d05d0 100644 (file)
@@ -3,5 +3,7 @@ NAME         dotnet-launcher
 EXE          /usr/bin/dotnet-launcher
 APP_TYPE     dotnet
 EXTRA_ARG    --PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE
+EXTRA_ARG    --appType
+EXTRA_ARG    dotnet
 EXTRA_ARG    --standalone
 
index 3422badd7acd0d9efb5548ec741d27832c4dc4f1..6cc183f9bea4c6dd5282966993098503ac95b5ce 100644 (file)
@@ -9,3 +9,4 @@ DETECTION_METHOD       TIMEOUT|DEMAND
 TIMEOUT                5000
 ON_BOOT                OFF
 HYDRA                  OFF
+EXTRA                  --appType                dotnet
index 5b59cf3a72b5e584d94f397318758c4041fe8d3a..3e45eb2824ec474517c852dce29694c56354c41b 100644 (file)
@@ -35,7 +35,7 @@ const char* __coreclr_lib = "/usr/share/dotnet.tizen/netcoreapp/libcoreclr.so";
 const char* __dotnet_loader = "/usr/bin/dotnet-loader";
 
 typedef int (*coreclr_preload_assembly_ptr)(const char* assemblyPath);
-typedef int (*launcher_real_main_ptr)(int argc, char *argv[], const char* mode);
+typedef int (*launcher_real_main_ptr)(int argc, char *argv[]);
 
 static std::string getAbsolutePath(const std::string& path)
 {
@@ -212,7 +212,7 @@ int main(int argc, char** argv)
                        return -1;
                }
 
-               return realMain(argc, argv, "default");
+               return realMain(argc, argv);
        };
 
        hydra_callback.terminate = [](void* user_data)-> int {
index 2a8ff56a921f8159a765aaf172882b10f8544f22..e00b628d9b4db59bcfef075c7db35c6b6d3545e0 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "coreclr_host.h"
 
-typedef void (*plugin_initialize_ptr)(const char* mode);
+typedef void (*plugin_initialize_ptr)(const char* appType);
 typedef void (*plugin_preload_ptr)();
 typedef void (*plugin_set_app_info_ptr)(
                        const char* appId,
@@ -57,7 +57,7 @@ void pluginBeforeExecute();
 void pluginFinalize();
 
 // initialize / finalize plugin manager
-int initializePluginManager(const char* mode);
+int initializePluginManager(const char* appType);
 void finalizePluginManager();
 
 #endif /* __PLUGIN_MANAGER_H__ */
index 37b0743df8d180d7a99fc2d4d81849e32be41cba..a302bb40e3fbe434936412ff2b7e836e32558b03 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "dotnet_launcher.h"
+#include "core_runtime.h"
 #include "utils.h"
 #include "log.h"
 
@@ -38,6 +38,7 @@ using tizen::runtime::dotnetcore::CoreRuntime;
 
 static std::string StandaloneOption("--standalone");
 static std::string PaddingOption("--PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE");
+static std::string AppTypeOption("--appType");
 
 int main(int argc, char *argv[])
 {
@@ -45,6 +46,7 @@ int main(int argc, char *argv[])
 
        char* standalonePath = nullptr;
        bool paddingExist = false;
+       const char* appType = NULL;
        const char* appRootPath = NULL;
        char appId[APPID_MAX_LENGTH] = {0,};
 
@@ -61,12 +63,21 @@ int main(int argc, char *argv[])
                        standalonePath = argv[i];
                } else if (PaddingOption.compare(argv[i]) == 0) {
                        paddingExist = true;
+               } else if (AppTypeOption.compare(argv[i]) == 0) {
+                       if (i > argc - 1) {
+                               _ERR("app type for launchpad must be after \"--appType\" option");
+                               return -1;
+                       }
+                       i++;
+                       appType = argv[i];
                } else {
                        vargs.push_back(argv[i]);
                }
        }
 
-       std::unique_ptr<CoreRuntime> runtime(new CoreRuntime("standalone"));
+       if (appType == NULL) {
+               appType = "dotnet";
+       }
 
        // get app ID and app root path
        if (AUL_R_OK == aul_app_get_appid_bypid(getpid(), appId, sizeof(appId))) {
@@ -90,17 +101,20 @@ int main(int argc, char *argv[])
        memset(argv[0], '\0', cmdlineSize);
        snprintf(argv[0], cmdlineSize - 1, "%s", standalonePath);
 
-       // initialize CoreRuntime (standalone mode enable, dlog redirection enable, root path NULL)
-       if (runtime->initialize(LaunchMode::launcher) != 0) {
+       // initialize CoreRuntime
+       if (CoreRuntime::initialize(appType, LaunchMode::launcher) != 0) {
                _ERR("Failed to initialize");
                return -1;
        }
 
        // launch application
-       if (runtime->launch(appId, appRootPath, standalonePath, vargs.size(), &vargs[0])) {
+       if (CoreRuntime::launch(appId, appRootPath, standalonePath, vargs.size(), &vargs[0])) {
                _ERR("Failed to launch");
                return -1;
        }
 
+       // finalize runtime
+       CoreRuntime::finalize();
+
        return 0;
 }
index 222de0a00da75b7d2f317711f922c5223fee2519..0669593314ac82315896bba07afc0b0dadfb720a 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "dotnet_launcher.h"
+#include "core_runtime.h"
 #include "utils.h"
 #include "log.h"
 
@@ -32,6 +32,8 @@
 
 using tizen::runtime::dotnetcore::CoreRuntime;
 
+static const char* KEY_APP_TYPE = "--appType";
+
 static Ecore_Fd_Handler *__fd_handler;
 static loader_receiver_cb __receiver;
 
@@ -114,14 +116,12 @@ static void __adapter_remove_fd(void *user_data, int fd)
 
 static void __loader_create_cb(bundle *extra, int type, void *user_data)
 {
-       CoreRuntime* runtime = (CoreRuntime*)user_data;
-
-       {
-               // do native window precreation here
+       char *appType = NULL;
+       if (bundle_get_str(extra, KEY_APP_TYPE, &appType) != BUNDLE_ERROR_NONE) {
+               appType = NULL;
        }
 
-       // initialize CoreRuntime (launchmode, dlog redirection enable, root path NULL)
-       if (runtime->initialize(LaunchMode::loader) != 0) {
+       if (CoreRuntime::initialize(appType ? appType : "dotnet", LaunchMode::loader) != 0) {
                _ERR("Failed to initialized");
        } else {
                _INFO("Success to initialized");
@@ -146,15 +146,14 @@ static int __loader_launch_cb(int argc, char **argv, const char *app_path,
 
 static int __loader_terminate_cb(int argc, char **argv, void *user_data)
 {
-       CoreRuntime* runtime = (CoreRuntime*)user_data;
-
        _INFO("launch request with app path : %s", __appInfo.app_path.c_str());
 
        // The launchpad pass the name of exe file to the first argument.
        // For the C# spec, we have to skip this first argument.
-       if (runtime->launch(__appInfo.appid.c_str(), __appInfo.root.c_str(),
+       if (CoreRuntime::launch(__appInfo.appid.c_str(), __appInfo.root.c_str(),
                                                __appInfo.app_path.c_str(), argc - 1, argv + 1)) {
                _ERR("Failed to launch");
+               return -1;
        }
 
        return 0;
@@ -162,12 +161,10 @@ static int __loader_terminate_cb(int argc, char **argv, void *user_data)
 
 //################## Main Code #################################################
 
-extern "C" int realMain(int argc, char *argv[], const char* mode)
+extern "C" int realMain(int argc, char *argv[])
 {
        _INFO("##### Run in candidate mode #####");
 
-       CoreRuntime* runtime = new CoreRuntime(mode);
-
        // change cmdline from dotnet-hydra-loader to dotnet-loader
        if (strcmp(argv[0], "/usr/bin/dotnet-hydra-loader") == 0) {
                memset(argv[0], '\0', strlen("/usr/bin/dotnet-hydra-loader"));
@@ -190,8 +187,10 @@ extern "C" int realMain(int argc, char *argv[], const char* mode)
                .remove_fd = __adapter_remove_fd
        };
 
-       int ret = launchpad_loader_main(argc, argv, &callbacks, &adapter, runtime);
-       delete runtime;
+       int ret = launchpad_loader_main(argc, argv, &callbacks, &adapter, NULL);
+       if (ret >= 0) {
+               CoreRuntime::finalize();
+       }
 
        return ret;
 }
@@ -201,5 +200,5 @@ int main(int argc, char *argv[])
        __argc = argc;
        __argv = argv;
 
-       return realMain(argc, argv, "candidate");
+       return realMain(argc, argv);
 }
diff --git a/NativeLauncher/launcher/lib/core_runtime.cc b/NativeLauncher/launcher/lib/core_runtime.cc
new file mode 100644 (file)
index 0000000..3fd90bb
--- /dev/null
@@ -0,0 +1,627 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#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 "core_runtime.h"
+#include "plugin_manager.h"
+#include "path_manager.h"
+#include "log_manager.h"
+
+namespace tizen {
+namespace runtime {
+namespace dotnetcore {
+
+static coreclr_initialize_ptr initializeClr = nullptr;
+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 void* __coreclrLib = nullptr;
+static void* __hostHandle = nullptr;
+static unsigned int __domainId = -1;
+static int __fd = -1;
+static bool __initialized = false;
+static bool __isProfileMode = false;
+
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+
+#ifdef NATIVE_LIB_DIR
+static std::string __nativeLibDirectory = __STR(NATIVE_LIB_DIR);
+#endif
+
+#undef __STR
+#undef __XSTR
+
+#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;
+       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_GRAPH.push_back(std::string("tizen." + version[i] + "-" + ARCHITECTURE_IDENTIFIER));
+                       RID_FALLBACK_GRAPH.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;
+       }
+}
+
+// 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);
+       setlocale(LC_ALL, const_cast<char *>(lang));
+
+       free(lang);
+}
+
+static std::string readSelfPath()
+{
+       char buff[PATH_MAX];
+       ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
+       if (len != -1) {
+               buff[len] = '\0';
+               return std::string(buff);
+       }
+
+       return "";
+}
+
+void preload()
+{
+       typedef void (*PreloadDelegate)();
+       PreloadDelegate preloadDelegate;
+
+       int ret = createDelegate(__hostHandle,
+               __domainId,
+               "Tizen.Runtime",
+               "Tizen.Runtime.Preloader",
+               "Preload",
+               (void**)&preloadDelegate);
+
+       if (ret < 0) {
+               _ERR("Failed to create delegate for Tizen.Runtime Preload (0x%08x)", ret);
+       } else {
+               preloadDelegate();
+       }
+}
+
+bool initializeCoreClr(const char* appId,
+                                                                        const char* assemblyProbePaths,
+                                                                        const char* NIProbePaths,
+                                                                        const char* pinvokeProbePaths,
+                                                                        const char* tpaList)
+{
+       const char *propertyKeys[] = {
+               "TRUSTED_PLATFORM_ASSEMBLIES",
+               "APP_PATHS",
+               "APP_NI_PATHS",
+               "NATIVE_DLL_SEARCH_DIRECTORIES",
+               "AppDomainCompatSwitch"
+       };
+
+       const char *propertyValues[] = {
+               tpaList,
+               assemblyProbePaths,
+               NIProbePaths,
+               pinvokeProbePaths,
+               "UseLatestBehaviorWhenTFMNotSpecified"
+       };
+
+       std::string selfPath = readSelfPath();
+
+       int st = initializeClr(selfPath.c_str(),
+                                                       appId,
+                                                       sizeof(propertyKeys) / sizeof(propertyKeys[0]),
+                                                       propertyKeys,
+                                                       propertyValues,
+                                                       &__hostHandle,
+                                                       &__domainId);
+
+       if (st < 0) {
+               _ERR("initialize core clr fail! (0x%08x)", st);
+               return false;
+       }
+
+       pluginSetCoreclrInfo(__hostHandle, __domainId, createDelegate);
+
+       _INFO("Initialize core clr success");
+       return true;
+}
+
+int CoreRuntime::initialize(const char* appType, LaunchMode launchMode)
+{
+       if (__initialized) {
+               _ERR("CoreRuntime is already initialized");
+               return -1;
+       }
+
+       // 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")) {
+               _INFO("profiling mode on");
+               __isProfileMode = true;
+       }
+
+       // plugin initialize should be called before creating threads.
+       // 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 creating threads.
+       if (initializePluginManager(appType) < 0) {
+               _ERR("Failed to initialize PluginManager");
+       }
+
+       // 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;
+       }
+
+#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.
+       // Therefore let's disable stack unwinding using DWARF information
+       // See https://github.com/dotnet/coreclr/issues/6698
+       //
+       // libunwind use following methods to unwind stack frame.
+       // UNW_ARM_METHOD_ALL          0xFF
+       // UNW_ARM_METHOD_DWARF        0x01
+       // UNW_ARM_METHOD_FRAME        0x02
+       // UNW_ARM_METHOD_EXIDX        0x04
+       putenv(const_cast<char *>("UNW_ARM_UNWIND_METHOD=6"));
+#endif // __arm__
+
+       // Enable diagnostics.
+       // clr create clr-debug-pipe-xxx and dotnet-diagnostics-xxx file under /tmp dir.
+       putenv(const_cast<char *>("COMPlus_EnableDiagnostics=1"));
+
+       // Write Debug.WriteLine to stderr
+       putenv(const_cast<char *>("COMPlus_DebugWriteToStdErr=1"));
+
+#ifdef USE_DEFAULT_BASE_ADDR
+       putenv(const_cast<char *>("COMPlus_UseDefaultBaseAddr=1"));
+#endif // USE_DEFAULT_BASE_ADDR
+
+       // 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;
+       }
+
+       if (!pluginHasLogControl()) {
+               if (initializeLogManager() < 0) {
+                       _ERR("Failed to initnialize LogManager");
+                       return -1;
+               }
+       }
+
+       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);
+               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) \
+       do { \
+               variable = (type)dlsym(__coreclrLib, name); \
+               if (variable == nullptr) { \
+                       _ERR(name " is not found in the libcoreclr.so"); \
+                       return -1; \
+               } \
+       } while (0)
+
+       CORELIB_RETURN_IF_NOSYM(coreclr_initialize_ptr, initializeClr, "coreclr_initialize");
+       CORELIB_RETURN_IF_NOSYM(coreclr_execute_assembly_ptr, executeAssembly, "coreclr_execute_assembly");
+       CORELIB_RETURN_IF_NOSYM(coreclr_shutdown_ptr, shutdown, "coreclr_shutdown");
+       CORELIB_RETURN_IF_NOSYM(coreclr_create_delegate_ptr, createDelegate, "coreclr_create_delegate");
+
+#undef CORELIB_RETURN_IF_NOSYM
+
+       _INFO("libcoreclr dlopen and dlsym success");
+
+       // 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);
+       if (__fd < 0) {
+               _ERR("Failed to open /proc/self");
+               return -1;
+       }
+
+       std::string tpa = getTPA();
+       std::string runtimeDir = getRuntimeDir();
+       std::string appName = std::string("dotnet-launcher-") + std::to_string(getpid());
+       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 = appRoot + ":" + appBin + ":" + appLib + ":" + appTac;
+       std::string NIprobePath = concatPath(appBin, APP_NI_SUB_DIR) + ":" + concatPath(appLib, APP_NI_SUB_DIR) + ":" + appTac;
+       std::string nativeLibPath = runtimeDir + ":" + __nativeLibDirectory + ":" + getExtraNativeLibDirs(appRoot) + ":" + appBin + ":" + appLib;
+
+       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, "Tizen.Runtime", "Tizen.Runtime.Environment", "SetEnvironmentVariable", (void**)&setEnvironmentVariable);
+       if (st < 0 || setEnvironmentVariable == nullptr) {
+               _ERR("Create delegate for Tizen.Runtime.dll -> Tizen.Runtime.Environment -> SetEnvironmentVariable failed (0x%08x)", st);
+               return -1;
+       }
+
+       __initialized = true;
+
+       if (launchMode == LaunchMode::loader) {
+               // terminate candidate process if language is changed.
+               // CurrentCulture created for preloaded dlls should be updated.
+               vconf_notify_key_changed(VCONFKEY_LANGSET, langChangedCB, NULL);
+
+               pluginPreload();
+               preload();              // Preload common managed code
+       }
+
+       _INFO("CoreRuntime initialize success");
+
+       return 0;
+}
+
+void CoreRuntime::finalize()
+{
+       if (!__initialized) {
+               _ERR("Runtime is not initialized");
+               return;
+       }
+
+       // call plugin finalize function to notify finalize to plugin
+       // dlclose shoud be done after coreclr shutdown to avoid breaking signal chain
+       pluginFinalize();
+
+       // ignore the signal generated by an exception that occurred during shutdown
+       checkOnTerminate = true;
+
+       // 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);
+       }
+
+       if (__hostHandle != nullptr) {
+               int st = shutdown(__hostHandle, __domainId);
+               if (st < 0)
+                       _ERR("shutdown core clr fail! (0x%08x)", st);
+               __hostHandle = nullptr;
+       }
+
+       if (__coreclrLib != nullptr) {
+               if (dlclose(__coreclrLib) != 0) {
+                       _ERR("libcoreclr.so close failed");
+               }
+
+               __coreclrLib = nullptr;
+       }
+
+       finalizePluginManager();
+       finalizePathManager();
+
+       __envList.clear();
+
+       _INFO("CoreRuntime finalized");
+}
+
+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;
+       }
+
+       if (!isFile(path)) {
+               _ERR("File not exist : %s", path);
+               return -1;
+       }
+
+       // 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;
+       }
+
+       // VD has their own signal handler.
+       if (!pluginHasLogControl()) {
+               registerSigHandler();
+       }
+
+       pluginSetAppInfo(appId, path);
+
+       // override root path for application launch mode (candidate / standalone mode)
+       if (__fd >= 0) {
+               int fd2 = open(root, O_DIRECTORY);
+               dup3(fd2, __fd, O_CLOEXEC);
+               if (fd2 >= 0)
+                       close(fd2);
+       }
+
+       // 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);
+       }
+
+       vconf_ignore_key_changed(VCONFKEY_LANGSET, langChangedCB);
+
+       pluginBeforeExecute();
+
+       _INFO("execute assembly : %s", path);
+
+       unsigned int ret = 0;
+       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;
+}
+
+}  // namespace dotnetcore
+}  // namespace runtime
+}  // namespace tizen
diff --git a/NativeLauncher/launcher/lib/core_runtime.h b/NativeLauncher/launcher/lib/core_runtime.h
new file mode 100644 (file)
index 0000000..27b97b9
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CORE_RUNTIME_H__
+#define __CORE_RUNTIME_H__
+
+#include <string>
+
+#include "coreclr_host.h"
+#include "plugin_manager.h"
+
+enum LaunchMode {
+       corerun = 0,
+       loader,
+       launcher
+};
+
+namespace tizen {
+namespace runtime {
+namespace dotnetcore {
+
+class CoreRuntime
+{
+       public:
+               static int initialize(const char* appType, LaunchMode launchMode);
+               static void finalize();
+               static int launch(const char* appId, const char* root, const char* path, int argc, char* argv[]);
+};
+
+}  // dotnetcore
+}  // namespace runtime
+}  // namespace tizen
+
+#endif /* __CORE_RUNTIME_H__ */
diff --git a/NativeLauncher/launcher/lib/dotnet_launcher.cc b/NativeLauncher/launcher/lib/dotnet_launcher.cc
deleted file mode 100644 (file)
index 0a32533..0000000
+++ /dev/null
@@ -1,628 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#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 "dotnet_launcher.h"
-#include "plugin_manager.h"
-#include "path_manager.h"
-#include "log_manager.h"
-
-namespace tizen {
-namespace runtime {
-namespace dotnetcore {
-
-#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;
-       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_GRAPH.push_back(std::string("tizen." + version[i] + "-" + ARCHITECTURE_IDENTIFIER));
-                       RID_FALLBACK_GRAPH.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;
-       }
-}
-
-// 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);
-       setlocale(LC_ALL, const_cast<char *>(lang));
-
-       free(lang);
-}
-
-static std::string readSelfPath()
-{
-       char buff[PATH_MAX];
-       ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
-       if (len != -1) {
-               buff[len] = '\0';
-               return std::string(buff);
-       }
-
-       return "";
-}
-
-void CoreRuntime::preload()
-{
-       typedef void (*PreloadDelegate)();
-       PreloadDelegate preloadDelegate;
-
-       int ret = createDelegate(__hostHandle,
-               __domainId,
-               "Tizen.Runtime",
-               "Tizen.Runtime.Preloader",
-               "Preload",
-               (void**)&preloadDelegate);
-
-       if (ret < 0) {
-               _ERR("Failed to create delegate for Tizen.Runtime Preload (0x%08x)", ret);
-       } else {
-               preloadDelegate();
-       }
-}
-
-CoreRuntime::CoreRuntime(const char* mode) :
-       initializeClr(nullptr),
-       executeAssembly(nullptr),
-       shutdown(nullptr),
-       createDelegate(nullptr),
-       setEnvironmentVariable(nullptr),
-       __coreclrLib(nullptr),
-       __hostHandle(nullptr),
-       __domainId(-1),
-       __fd(-1),
-       __initialized(false),
-       __isProfileMode(false)
-{
-       _INFO("Constructor called!!");
-
-       // 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")) {
-               _INFO("profiling mode on");
-               __isProfileMode = true;
-       }
-
-       // 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(LaunchMode launchMode)
-{
-       // 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.
-       // Therefore let's disable stack unwinding using DWARF information
-       // See https://github.com/dotnet/coreclr/issues/6698
-       //
-       // libunwind use following methods to unwind stack frame.
-       // UNW_ARM_METHOD_ALL          0xFF
-       // UNW_ARM_METHOD_DWARF        0x01
-       // UNW_ARM_METHOD_FRAME        0x02
-       // UNW_ARM_METHOD_EXIDX        0x04
-       putenv(const_cast<char *>("UNW_ARM_UNWIND_METHOD=6"));
-#endif // __arm__
-
-       // Enable diagnostics.
-       // clr create clr-debug-pipe-xxx and dotnet-diagnostics-xxx file under /tmp dir.
-       putenv(const_cast<char *>("COMPlus_EnableDiagnostics=1"));
-
-       // Write Debug.WriteLine to stderr
-       putenv(const_cast<char *>("COMPlus_DebugWriteToStdErr=1"));
-
-#ifdef USE_DEFAULT_BASE_ADDR
-       putenv(const_cast<char *>("COMPlus_UseDefaultBaseAddr=1"));
-#endif // USE_DEFAULT_BASE_ADDR
-
-       // 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;
-       }
-
-       if (!pluginHasLogControl()) {
-               if (initializeLogManager() < 0) {
-                       _ERR("Failed to initnialize LogManager");
-                       return -1;
-               }
-       }
-
-       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);
-               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) \
-       do { \
-               variable = (type)dlsym(__coreclrLib, name); \
-               if (variable == nullptr) { \
-                       _ERR(name " is not found in the libcoreclr.so"); \
-                       return -1; \
-               } \
-       } while (0)
-
-       CORELIB_RETURN_IF_NOSYM(coreclr_initialize_ptr, initializeClr, "coreclr_initialize");
-       CORELIB_RETURN_IF_NOSYM(coreclr_execute_assembly_ptr, executeAssembly, "coreclr_execute_assembly");
-       CORELIB_RETURN_IF_NOSYM(coreclr_shutdown_ptr, shutdown, "coreclr_shutdown");
-       CORELIB_RETURN_IF_NOSYM(coreclr_create_delegate_ptr, createDelegate, "coreclr_create_delegate");
-
-#undef CORELIB_RETURN_IF_NOSYM
-
-       _INFO("libcoreclr dlopen and dlsym success");
-
-       if (launchMode == LaunchMode::loader) {
-               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
-       // 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);
-       if (__fd < 0) {
-               _ERR("Failed to open /proc/self");
-               return -1;
-       }
-
-       std::string tpa = getTPA();
-       std::string runtimeDir = getRuntimeDir();
-       std::string appName = std::string("dotnet-launcher-") + std::to_string(getpid());
-       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 = appRoot + ":" + appBin + ":" + appLib + ":" + appTac;
-       std::string NIprobePath = concatPath(appBin, APP_NI_SUB_DIR) + ":" + concatPath(appLib, APP_NI_SUB_DIR) + ":" + appTac;
-       std::string nativeLibPath = runtimeDir + ":" + __nativeLibDirectory + ":" + getExtraNativeLibDirs(appRoot) + ":" + appBin + ":" + appLib;
-
-       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, "Tizen.Runtime", "Tizen.Runtime.Environment", "SetEnvironmentVariable", (void**)&setEnvironmentVariable);
-       if (st < 0 || setEnvironmentVariable == nullptr) {
-               _ERR("Create delegate for Tizen.Runtime.dll -> Tizen.Runtime.Environment -> SetEnvironmentVariable failed (0x%08x)", st);
-               return -1;
-       }
-
-       __initialized = true;
-
-       if (launchMode == LaunchMode::loader) {
-               preload();              // 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)
-{
-       const char *propertyKeys[] = {
-               "TRUSTED_PLATFORM_ASSEMBLIES",
-               "APP_PATHS",
-               "APP_NI_PATHS",
-               "NATIVE_DLL_SEARCH_DIRECTORIES",
-               "AppDomainCompatSwitch"
-       };
-
-       const char *propertyValues[] = {
-               tpaList,
-               assemblyProbePaths,
-               NIProbePaths,
-               pinvokeProbePaths,
-               "UseLatestBehaviorWhenTFMNotSpecified"
-       };
-
-       std::string selfPath = readSelfPath();
-
-       int st = initializeClr(selfPath.c_str(),
-                                                       appId,
-                                                       sizeof(propertyKeys) / sizeof(propertyKeys[0]),
-                                                       propertyKeys,
-                                                       propertyValues,
-                                                       &__hostHandle,
-                                                       &__domainId);
-
-       if (st < 0) {
-               _ERR("initialize core clr fail! (0x%08x)", st);
-               return false;
-       }
-
-       pluginSetCoreclrInfo(__hostHandle, __domainId, createDelegate);
-
-       _INFO("Initialize core clr success");
-       return true;
-}
-
-void CoreRuntime::dispose()
-{
-       // call plugin finalize function to notify finalize to plugin
-       // dlclose shoud be done after coreclr shutdown to avoid breaking signal chain
-       pluginFinalize();
-
-       // ignore the signal generated by an exception that occurred during shutdown
-       checkOnTerminate = true;
-
-       if (__hostHandle != nullptr) {
-               int st = shutdown(__hostHandle, __domainId);
-               if (st < 0)
-                       _ERR("shutdown core clr fail! (0x%08x)", st);
-               __hostHandle = nullptr;
-       }
-
-       if (__coreclrLib != nullptr) {
-               if (dlclose(__coreclrLib) != 0) {
-                       _ERR("libcoreclr.so close failed");
-               }
-
-               __coreclrLib = nullptr;
-       }
-
-       finalizePluginManager();
-       finalizePathManager();
-
-       __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;
-       }
-
-       if (!isFile(path)) {
-               _ERR("File not exist : %s", path);
-               return -1;
-       }
-
-       // 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;
-       }
-
-       // VD has their own signal handler.
-       if (!pluginHasLogControl()) {
-               registerSigHandler();
-       }
-
-       pluginSetAppInfo(appId, path);
-
-       // override root path for application launch mode (candidate / standalone mode)
-       if (__fd >= 0) {
-               int fd2 = open(root, O_DIRECTORY);
-               dup3(fd2, __fd, O_CLOEXEC);
-               if (fd2 >= 0)
-                       close(fd2);
-       }
-
-       // 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);
-       }
-
-       vconf_ignore_key_changed(VCONFKEY_LANGSET, langChangedCB);
-
-       pluginBeforeExecute();
-
-       _INFO("execute assembly : %s", path);
-
-       unsigned int ret = 0;
-       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;
-}
-
-}  // namespace dotnetcore
-}  // namespace runtime
-}  // namespace tizen
diff --git a/NativeLauncher/launcher/lib/dotnet_launcher.h b/NativeLauncher/launcher/lib/dotnet_launcher.h
deleted file mode 100644 (file)
index ddaabd6..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __DOTNET_LAUNCHER_H__
-#define __DOTNET_LAUNCHER_H__
-
-#include <string>
-
-#include "coreclr_host.h"
-#include "plugin_manager.h"
-
-enum LaunchMode {
-       corerun = 0,
-       loader,
-       launcher
-};
-
-namespace tizen {
-namespace runtime {
-namespace dotnetcore {
-
-class CoreRuntime
-{
-       public:
-               CoreRuntime(const char* mode);
-               ~CoreRuntime();
-               int initialize(LaunchMode mode);
-               void dispose();
-               int launch(const char* appId, const char* root, const char* path, int argc, char* argv[]);
-
-       private:
-               bool initializeCoreClr(const char* appId, const char* assemblyProbePaths, const char* NIProbePaths, const char* pinvokeProbePaths, const char* tpaList);
-               void preload();
-               coreclr_initialize_ptr initializeClr;
-               coreclr_execute_assembly_ptr executeAssembly;
-               coreclr_shutdown_ptr shutdown;
-               coreclr_create_delegate_ptr createDelegate;
-               set_environment_variable_ptr setEnvironmentVariable;
-               std::string __nativeLibDirectory;
-               void* __coreclrLib;
-               void* __hostHandle;
-               unsigned int __domainId;
-               int __fd;
-               bool __initialized;
-               bool __isProfileMode;
-};
-
-}  // dotnetcore
-}  // namespace runtime
-}  // namespace tizen
-
-#endif /* __DOTNET_LAUNCHER_H__ */
index e4025769ee9ef780733bff76dd6730d81f28ab07..d0e829ea636a975f5c5bc3ad7b3d9ce0d56cc775 100644 (file)
@@ -24,7 +24,7 @@ static PluginFunc* __pluginFunc = NULL;
 static void* __pluginLib;
 bool initializedPluginManager = false;
 
-int initializePluginManager(const char* mode)
+int initializePluginManager(const char* appType)
 {
        if (initializedPluginManager) {
                _INFO("Plugin manager already initialized");
@@ -51,10 +51,10 @@ int initializePluginManager(const char* mode)
                }
 
                if (__pluginFunc->initialize)
-                       __pluginFunc->initialize(mode);
+                       __pluginFunc->initialize(appType);
        }
 
-       _INFO("Plugin manager initialize success");
+       _INFO("Plugin manager initialize success : appType(%s)", appType);
 
        initializedPluginManager = true;
        return 0;