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})
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
TIMEOUT 5000
ON_BOOT OFF
HYDRA OFF
+EXTRA --appType dotnet
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)
{
return -1;
}
- return realMain(argc, argv, "default");
+ return realMain(argc, argv);
};
hydra_callback.terminate = [](void* user_data)-> int {
#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,
void pluginFinalize();
// initialize / finalize plugin manager
-int initializePluginManager(const char* mode);
+int initializePluginManager(const char* appType);
void finalizePluginManager();
#endif /* __PLUGIN_MANAGER_H__ */
* limitations under the License.
*/
-#include "dotnet_launcher.h"
+#include "core_runtime.h"
#include "utils.h"
#include "log.h"
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[])
{
char* standalonePath = nullptr;
bool paddingExist = false;
+ const char* appType = NULL;
const char* appRootPath = NULL;
char appId[APPID_MAX_LENGTH] = {0,};
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))) {
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;
}
* limitations under the License.
*/
-#include "dotnet_launcher.h"
+#include "core_runtime.h"
#include "utils.h"
#include "log.h"
using tizen::runtime::dotnetcore::CoreRuntime;
+static const char* KEY_APP_TYPE = "--appType";
+
static Ecore_Fd_Handler *__fd_handler;
static loader_receiver_cb __receiver;
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");
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;
//################## 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"));
.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;
}
__argc = argc;
__argv = argv;
- return realMain(argc, argv, "candidate");
+ return realMain(argc, argv);
}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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__ */
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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__ */
static void* __pluginLib;
bool initializedPluginManager = false;
-int initializePluginManager(const char* mode)
+int initializePluginManager(const char* appType)
{
if (initializedPluginManager) {
_INFO("Plugin manager already initialized");
}
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;