#include <vector>
#include <sstream>
+#include <locale>
+#include <codecvt>
+
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <storage.h>
#include <app_common.h>
+#include "injection.h"
#include "utils.h"
#include "log.h"
#include "launcher.h"
#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 {
#elif defined (__arm__)
#define ARCHITECTURE_IDENTIFIER "arm"
const static std::vector<std::string> 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"
#elif defined (__i386__)
#define ARCHITECTURE_IDENTIFIER "x86"
const static std::vector<std::string> 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"
}
}
+#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)
{
- // ignore return value of write().
- // this function is called when process go to die
- // there is no need to handle return value for logging.
- write(2, "onSigabrt called\n", 17);
+ // 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) {
- write(2, "onSigabrt called again. go to exit\n", 35);
+ ret = write(STDERR_FILENO, "onSigabrt called again. go to exit\n", 35);
+ _unused(ret);
exit(0);
}
if (hasException()) {
- write(2, "Unhandled exception is occured. Ignore coredump creation and terminate normally\n", 80);
- exit(0);
- } else {
- write(2, "SIGABRT from native. raise SIGABRT\n", 35);
- checkOnSigabrt = true;
- if (sigaction(SIGABRT, &sig_abrt_old, NULL) == 0) {
- if (raise(signum) < 0) {
- write(2, "Fail to raise SIGABRT\n", 22);
- }
- } else {
- write(2, "Fail to set original SIGABRT handler\n", 37);
+ 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()
}
}
+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),
- multiByteToWideChar(nullptr),
__coreclrLib(nullptr),
__hostHandle(nullptr),
__domainId(-1),
int CoreRuntime::initialize(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)
putenv(const_cast<char *>("UNW_ARM_UNWIND_METHOD=6"));
#endif // __arm__
+ // Disable debug pipes and semaphores creation in case of non-standlone mode
+ if (!standalone)
+ putenv(const_cast<char *>("COMPlus_EnableDiagnostics=0"));
+
+ // 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();
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");
- CORELIB_RETURN_IF_NOSYM(set_environment_variable_ptr, setEnvironmentVariable, "SetEnvironmentVariableW");
- CORELIB_RETURN_IF_NOSYM(multi_byte_to_wide_char_ptr, multiByteToWideChar, "MultiByteToWideChar");
#undef CORELIB_RETURN_IF_NOSYM
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;
bool CoreRuntime::initializeCoreClr(const char* appId,
const char* assemblyProbePaths,
+ const char* NIProbePaths,
const char* pinvokeProbePaths,
const char* tpaList)
{
const char *propertyValues[] = {
tpaList,
assemblyProbePaths,
- assemblyProbePaths,
+ NIProbePaths,
pinvokeProbePaths,
"UseLatestBehaviorWhenTFMNotSpecified"
};
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)
// 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) {
- char16_t envval[PATH_MAX] = {0};
- int copied = multiByteToWideChar(0 /* CP_ACP */, 0, localDataPath, -1, envval, PATH_MAX);
- if (copied >= PATH_MAX) {
- _ERR("Data Path is bigger than PATH_MAX");
- }
-
- if (!setEnvironmentVariable(u"XDG_DATA_HOME", envval)) {
- _ERR("Failed to set XDG_DATA_HOME");
- }
+ setEnvironmentVariable("XDG_DATA_HOME", localDataPath);
+ free(localDataPath);
}
pluginBeforeExecute();