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);
}
#include "injection.h"
#include "utils.h"
#include "log.h"
-#include "dotnet_launcher.h"
+#include "core_runtime.h"
#include "plugin_manager.h"
#include "path_manager.h"
#include "log_manager.h"
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"
return "";
}
-void CoreRuntime::preload()
+void preload()
{
typedef void (*PreloadDelegate)();
PreloadDelegate 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)
+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)
{
- _INFO("Constructor called!!");
+ if (__initialized) {
+ _ERR("CoreRuntime is already initialized");
+ return -1;
+ }
// Intiailize ecore first (signal handlers, etc.) before runtime init.
ecore_init();
__isProfileMode = true;
}
- // plugin initialize should be called before start loader mainloop.
+ // 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 mainloop start.
- if (initializePluginManager(mode) < 0) {
+ // So, plugin initialize should be called before creating threads.
+ if (initializePluginManager(appType) < 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();
_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
_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.
__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
}
return 0;
}
-bool CoreRuntime::initializeCoreClr(const char* appId,
- const char* assemblyProbePaths,
- const char* NIProbePaths,
- const char* pinvokeProbePaths,
- const char* tpaList)
+void CoreRuntime::finalize()
{
- 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;
+ if (!__initialized) {
+ _ERR("Runtime is not initialized");
+ return;
}
- 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;
+ // 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)
__envList.clear();
- _INFO("Dotnet runtime disposed");
+ _INFO("CoreRuntime finalized");
}
int CoreRuntime::launch(const char* appId, const char* root, const char* path, int argc, char* argv[])
* limitations under the License.
*/
-#ifndef __DOTNET_LAUNCHER_H__
-#define __DOTNET_LAUNCHER_H__
+#ifndef __CORE_RUNTIME_H__
+#define __CORE_RUNTIME_H__
#include <string>
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;
+ 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 /* __DOTNET_LAUNCHER_H__ */
+#endif /* __CORE_RUNTIME_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;