X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=NativeLauncher%2Flauncher%2Fdotnet%2Fdotnet_launcher.cc;h=c13c4068009bb330645cb7fb75922e670f3b88ff;hb=92d8fe2e5a122d3d499fb7186176c5df60a52d10;hp=2e659278065e62660b1a6779bd72d263512cdbe7;hpb=3f59fa85cbb2a7e0f1ca58b1536fb625778924be;p=platform%2Fcore%2Fdotnet%2Flauncher.git diff --git a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc index 2e65927..c13c406 100644 --- a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc +++ b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc @@ -16,18 +16,27 @@ #include +#include #include #include #include #include +#include +#include + #include #include #include #include #include +#include + +#include +#include +#include "injection.h" #include "utils.h" #include "log.h" #include "launcher.h" @@ -36,9 +45,6 @@ #include "path_manager.h" #include "log_manager.h" -#define PLUGIN_PATH "/usr/share/dotnet.tizen/lib/libdotnet_plugin.so" -#define ENV_FILE_PATH "/usr/share/dotnet.tizen/lib/coreclr_env.list" - namespace tizen { namespace runtime { namespace dotnetcore { @@ -51,7 +57,7 @@ const static std::vector RID_FALLBACK_GRAPH = #elif defined (__arm__) #define ARCHITECTURE_IDENTIFIER "arm" const static std::vector RID_FALLBACK_GRAPH = - {"tizen.4.0.0-armel", "tizen.4.0.0", "tizen-armel", "tizen", "linux-armel", "linux", "unix-armel", "unix", "any", "base"}; + {"tizen.5.0.0-armel", "tizen.5.0.0", "tizen.4.0.0-armel", "tizen.4.0.0", "tizen-armel", "tizen", "linux-armel", "linux", "unix-armel", "unix", "any", "base"}; #elif defined (__x86_64__) #define ARCHITECTURE_IDENTIFIER "x64" @@ -61,7 +67,7 @@ const static std::vector RID_FALLBACK_GRAPH = #elif defined (__i386__) #define ARCHITECTURE_IDENTIFIER "x86" const static std::vector RID_FALLBACK_GRAPH = - {"linux-x86", "linux", "unix-x86", "unix", "any", "base"}; + {"tizen.5.0.0-x86", "tizen.5.0.0", "tizen.4.0.0-x86", "tizen.4.0.0", "tizen-x86", "tizen", "linux-x86", "linux", "unix-x86", "unix", "any", "base"}; #else #error "Unknown target" @@ -116,19 +122,152 @@ static void setEnvFromFile() } } +#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); + } + + if (hasException()) { + ret = write(STDERR_FILENO, "******************************************************\n", 55); + ret = write(STDERR_FILENO, "Unhandled exception is occured. check application code\n", 55); + ret = write(STDERR_FILENO, "******************************************************\n", 55); + } + + 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(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(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(path), 1); + free(path); + path = NULL; + } +} + +void CoreRuntime::preloadTypes() +{ + const static std::string initDllPath = "/usr/share/dotnet.tizen/framework/Tizen.Init.dll"; + if (!isFileExist(initDllPath)) { + _ERR("Failed to locate Tizen.Init.dll"); + return; + } + + typedef void (*InitDelegate)(); + InitDelegate initDelegate; + + int ret = createDelegate(__hostHandle, + __domainId, + "Tizen.Init", + "Tizen.Init.TypeLoader", + "PreloadTypes", + (void**)&initDelegate); + + if (ret < 0) { + _ERR("Failed to create delegate for PreloadTypes (0x%08x)", ret); + } else { + initDelegate(); + } +} + CoreRuntime::CoreRuntime(const char* mode) : initializeClr(nullptr), executeAssembly(nullptr), shutdown(nullptr), createDelegate(nullptr), + setEnvironmentVariable(nullptr), __coreclrLib(nullptr), __hostHandle(nullptr), __domainId(-1), fd(0), - __initialized(false) + __initialized(false), + __isProfileMode(false) { _INFO("Constructor called!!"); + 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. @@ -136,15 +275,36 @@ CoreRuntime::CoreRuntime(const char* mode) : if (initializePluginManager(mode) < 0) { _ERR("Failed to initialize PluginManager"); } + + if (pluginHasLogControl()) { + __enableLogManager = false; + } else { + __enableLogManager = true; + } } CoreRuntime::~CoreRuntime() { + // workaround : to prevent crash while process terminate on profiling mode, + // kill process immediately. + // see https://github.com/dotnet/coreclr/issues/26687 + if (__isProfileMode) { + _INFO("shutdown process immediately."); + _exit(0); + } + dispose(); } -int CoreRuntime::initialize(bool standalone) +int CoreRuntime::preinitialize(bool standalone) { + // 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) @@ -169,35 +329,36 @@ int CoreRuntime::initialize(bool standalone) putenv(const_cast("UNW_ARM_UNWIND_METHOD=6")); #endif // __arm__ + // Disable debug pipes and semaphores creation in case of non-standlone mode + if (!standalone) + putenv(const_cast("COMPlus_EnableDiagnostics=0")); + + // Write Debug.WriteLine to stderr + putenv(const_cast("COMPlus_DebugWriteToStdErr=1")); + +#ifdef USE_DEFAULT_BASE_ADDR + putenv(const_cast("COMPlus_UseDefaultBaseAddr=1")); +#endif // USE_DEFAULT_BASE_ADDR + // read string from external file and set them to environment value. setEnvFromFile(); + // Set environment for System.Environment.SpecialFolder + initEnvForSpecialFolder(); + if (initializePathManager(std::string(), std::string(), std::string()) < 0) { _ERR("Failed to initialize PathManager"); return -1; } - if (initializeLogManager() < 0) { - _ERR("Failed to initnialize LogManager"); - return -1; - } - - if (redirectFD() < 0) { - _ERR("Failed to redirect FD"); - return -1; - } - - if (runLoggingThread() < 0) { - _ERR("Failed to create and run logging thread to redicrect log"); - 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; } @@ -219,6 +380,38 @@ int CoreRuntime::initialize(bool standalone) _INFO("libcoreclr dlopen and dlsym success"); + return 0; +} + +int CoreRuntime::initialize(bool standalone) +{ +#define __XSTR(x) #x +#define __STR(x) __XSTR(x) + +#ifdef NATIVE_LIB_DIR + __nativeLibDirectory = __STR(NATIVE_LIB_DIR); +#endif + +#undef __STR +#undef __XSTR + + if (__enableLogManager) { + if (initializeLogManager() < 0) { + _ERR("Failed to initnialize LogManager"); + return -1; + } + + if (redirectFD() < 0) { + _ERR("Failed to redirect FD"); + return -1; + } + + if (runLoggingThread() < 0) { + _ERR("Failed to create and run logging thread to redicrect log"); + return -1; + } + } + if (!standalone) pluginPreload(); @@ -226,18 +419,32 @@ int CoreRuntime::initialize(bool standalone) 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 probePath = appBin + ":" + appLib; + std::string appTac = concatPath(appBin, TAC_SYMLINK_SUB_DIR); + std::string probePath = appBin + ":" + appLib + ":" + appTac; + std::string NIprobePath = concatPath(appBin, APP_NI_SUB_DIR) + ":" + concatPath(appLib, APP_NI_SUB_DIR) + ":" + appTac; std::string tpa = getTPA(); - std::string nativeLibPath = getExtraNativeLibDirs(appRoot) + ":" + appBin + ":" + appLib + ":" + __nativeLibDirectory; + std::string runtimeDir = getRuntimeDir(); + std::string nativeLibPath = getExtraNativeLibDirs(appRoot) + ":" + appBin + ":" + appLib + ":" + __nativeLibDirectory + ":" + runtimeDir; std::string appName = std::string("dotnet-launcher-") + std::to_string(getpid()); - if (!initializeCoreClr(appName.c_str(), probePath.c_str(), nativeLibPath.c_str(), tpa.c_str())) { + if (!initializeCoreClr(appName.c_str(), probePath.c_str(), NIprobePath.c_str(), nativeLibPath.c_str(), tpa.c_str())) { _ERR("Failed to initialize coreclr"); return -1; } + int st = createDelegate(__hostHandle, __domainId, "Dotnet.Launcher", "Dotnet.Launcher.Environment", "SetEnvironmentVariable", (void**)&setEnvironmentVariable); + if (st < 0 || setEnvironmentVariable == nullptr) { + _ERR("Create delegate for Dotnet.Launcher.dll -> Dotnet.Launcher.Environment -> SetEnvironmentVariable failed (0x%08x)", st); + return -1; + } + __initialized = true; + if (!standalone) + { + preloadTypes(); // Preload common managed code + } + _INFO("CoreRuntime initialize success"); return 0; @@ -245,6 +452,7 @@ int CoreRuntime::initialize(bool standalone) bool CoreRuntime::initializeCoreClr(const char* appId, const char* assemblyProbePaths, + const char* NIProbePaths, const char* pinvokeProbePaths, const char* tpaList) { @@ -259,7 +467,7 @@ bool CoreRuntime::initializeCoreClr(const char* appId, const char *propertyValues[] = { tpaList, assemblyProbePaths, - assemblyProbePaths, + NIProbePaths, pinvokeProbePaths, "UseLatestBehaviorWhenTFMNotSpecified" }; @@ -287,6 +495,13 @@ bool CoreRuntime::initializeCoreClr(const char* appId, 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) @@ -327,11 +542,15 @@ int CoreRuntime::launch(const char* appId, const char* root, const char* path, i 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 (redirectFD() < 0) { - _ERR("Failed to redirect FD"); - return -1; + if (__enableLogManager) { + // launchpad override stdout and stderr to journalctl before launch application. + // we have to re-override that to input pipe for logging thread. + if (redirectFD() < 0) { + _ERR("Failed to redirect FD"); + return -1; + } + + registerSigHandler(); } pluginSetAppInfo(appId, path); @@ -341,6 +560,14 @@ int CoreRuntime::launch(const char* appId, const char* root, const char* path, i 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); + } + pluginBeforeExecute(); _INFO("execute assembly : %s", path);