From cb8248240f2a51953405aad2da49a17891d62e38 Mon Sep 17 00:00:00 2001 From: Woongsuk Cho Date: Thu, 26 Mar 2020 12:38:20 +0900 Subject: [PATCH] seperate executable to apply User execute label to dotnet-loader --- NativeLauncher/CMakeLists.txt | 62 ++++-- NativeLauncher/dotnet.loader | 6 +- NativeLauncher/hydra/hydra_main.cc | 4 +- NativeLauncher/inc/log.h | 17 +- NativeLauncher/inc/utils.h | 13 ++ NativeLauncher/launcher/exec/corerun.cc | 66 ++++++ NativeLauncher/launcher/exec/launcher.cc | 107 ++++++++++ NativeLauncher/launcher/exec/loader.cc | 203 ++++++++++++++++++ NativeLauncher/launcher/launcher.cc | 236 --------------------- NativeLauncher/launcher/launcher.h | 48 ----- .../launcher/{dotnet => lib}/dotnet_launcher.cc | 17 +- .../launcher/{dotnet => lib}/dotnet_launcher.h | 12 +- NativeLauncher/launcher/{ => lib}/injection.cc | 0 NativeLauncher/launcher/{ => lib}/injection.h | 0 NativeLauncher/launcher/main.cc | 170 --------------- NativeLauncher/util/utils.cc | 27 +++ dotnet-launcher.manifest | 2 + packaging/dotnet-launcher.spec | 8 +- 18 files changed, 504 insertions(+), 494 deletions(-) create mode 100644 NativeLauncher/launcher/exec/corerun.cc create mode 100644 NativeLauncher/launcher/exec/launcher.cc create mode 100644 NativeLauncher/launcher/exec/loader.cc delete mode 100644 NativeLauncher/launcher/launcher.cc delete mode 100644 NativeLauncher/launcher/launcher.h rename NativeLauncher/launcher/{dotnet => lib}/dotnet_launcher.cc (98%) rename NativeLauncher/launcher/{dotnet => lib}/dotnet_launcher.h (92%) rename NativeLauncher/launcher/{ => lib}/injection.cc (100%) rename NativeLauncher/launcher/{ => lib}/injection.h (100%) delete mode 100644 NativeLauncher/launcher/main.cc diff --git a/NativeLauncher/CMakeLists.txt b/NativeLauncher/CMakeLists.txt index d6cefa3..37d1e3f 100644 --- a/NativeLauncher/CMakeLists.txt +++ b/NativeLauncher/CMakeLists.txt @@ -10,7 +10,7 @@ FOREACH(flag ${${PROJECT_NAME}_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") ENDFOREACH(flag) -SET(target_hydra dotnet_hydra_launcher) +SET(target_hydra dotnet_hydra_loader) PKG_CHECK_MODULES(${target_hydra} REQUIRED liblaunchpad-hydra) @@ -114,29 +114,62 @@ ADD_LIBRARY(${DOTNET_LAUNCHER_UTIL} SHARED ${${DOTNET_LAUNCHER_UTIL}_SOURCE_FILE SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER_UTIL} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_LIB}) TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER_UTIL} ${${PROJECT_NAME}_LDFLAGS} "-ldl" boost_filesystem boost_system) +SET(DOTNET_LAUNCHER_CORE "dotnet_launcher_core") +SET(${DOTNET_LAUNCHER_CORE}_SOURCE_FILES + launcher/lib/injection.cc + launcher/lib/dotnet_launcher.cc +) +ADD_LIBRARY(${DOTNET_LAUNCHER_CORE} SHARED ${${DOTNET_LAUNCHER_CORE}_SOURCE_FILES}) +SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER_CORE} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_LIB}) +TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER_CORE} ${${PROJECT_NAME}_LDFLAGS} "-ldl" boost_filesystem boost_system ${DOTNET_LAUNCHER_UTIL}) + SET(DOTNET_LAUNCHER "dotnet-launcher") SET(${DOTNET_LAUNCHER}_SOURCE_FILES - launcher/main.cc - launcher/injection.cc - launcher/launcher.cc - launcher/dotnet/dotnet_launcher.cc + launcher/exec/launcher.cc ) ADD_EXECUTABLE(${DOTNET_LAUNCHER} ${${DOTNET_LAUNCHER}_SOURCE_FILES}) SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_EXE}) -TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl -lpthread" aul ${DOTNET_LAUNCHER_UTIL}) +TARGET_INCLUDE_DIRECTORIES(${DOTNET_LAUNCHER} PRIVATE "launcher/lib") +TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl -lpthread" aul ${DOTNET_LAUNCHER_UTIL} ${DOTNET_LAUNCHER_CORE}) SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER} PROPERTIES SKIP_BUILD_RPATH TRUE ) # remove rpath option that is automatically generated by cmake. -SET(DOTNET_HYDRA_LAUNCHER "dotnet-hydra-launcher") -SET(${DOTNET_HYDRA_LAUNCHER}_SOURCE_FILES +SET(DOTNET_LOADER "dotnet-loader") +SET(${DOTNET_LOADER}_SOURCE_FILES + launcher/exec/loader.cc +) +ADD_EXECUTABLE(${DOTNET_LOADER} ${${DOTNET_LOADER}_SOURCE_FILES}) +SET_TARGET_PROPERTIES(${DOTNET_LOADER} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_EXE}) +TARGET_INCLUDE_DIRECTORIES(${DOTNET_LOADER} PRIVATE "launcher/lib") +TARGET_LINK_LIBRARIES(${DOTNET_LOADER} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl -lpthread" aul ${DOTNET_LAUNCHER_UTIL} ${DOTNET_LAUNCHER_CORE}) + +SET_TARGET_PROPERTIES(${DOTNET_LOADER} + PROPERTIES SKIP_BUILD_RPATH TRUE +) # remove rpath option that is automatically generated by cmake. + +SET(DOTNET_CORERUN "dotnet") +SET(${DOTNET_CORERUN}_SOURCE_FILES + launcher/exec/corerun.cc +) +ADD_EXECUTABLE(${DOTNET_CORERUN} ${${DOTNET_CORERUN}_SOURCE_FILES}) +SET_TARGET_PROPERTIES(${DOTNET_CORERUN} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_EXE}) +TARGET_INCLUDE_DIRECTORIES(${DOTNET_CORERUN} PRIVATE "launcher/lib") +TARGET_LINK_LIBRARIES(${DOTNET_CORERUN} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl -lpthread" aul ${DOTNET_LAUNCHER_UTIL} ${DOTNET_LAUNCHER_CORE}) + +SET_TARGET_PROPERTIES(${DOTNET_CORERUN} + PROPERTIES SKIP_BUILD_RPATH TRUE +) # remove rpath option that is automatically generated by cmake. + +SET(DOTNET_HYDRA_LOADER "dotnet-hydra-loader") +SET(${DOTNET_HYDRA_LOADER}_SOURCE_FILES hydra/hydra_main.cc ) -ADD_EXECUTABLE(${DOTNET_HYDRA_LAUNCHER} ${${DOTNET_HYDRA_LAUNCHER}_SOURCE_FILES}) -TARGET_LINK_LIBRARIES(${DOTNET_HYDRA_LAUNCHER} ${${target_hydra}_LDFLAGS} "-pie -ldl") -SET_TARGET_PROPERTIES(${DOTNET_HYDRA_LAUNCHER} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_HYDRA}) -SET_TARGET_PROPERTIES(${DOTNET_HYDRA_LAUNCHER} +ADD_EXECUTABLE(${DOTNET_HYDRA_LOADER} ${${DOTNET_HYDRA_LOADER}_SOURCE_FILES}) +TARGET_LINK_LIBRARIES(${DOTNET_HYDRA_LOADER} ${${target_hydra}_LDFLAGS} "-pie -ldl") +SET_TARGET_PROPERTIES(${DOTNET_HYDRA_LOADER} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_HYDRA}) +SET_TARGET_PROPERTIES(${DOTNET_HYDRA_LOADER} PROPERTIES SKIP_BUILD_RPATH TRUE ) # remove rpath option that is automatically generated by cmake. @@ -200,8 +233,11 @@ TARGET_LINK_LIBRARIES(${PREFER_NUGET_CACHE_PLUGIN} ${${PROJECT_NAME}_LDFLAGS} ${ CONFIGURE_FILE(dotnet-launcher.pc.in dotnet-launcher.pc @ONLY) INSTALL(TARGETS ${DOTNET_LAUNCHER_UTIL} DESTINATION ${LIBDIR}) +INSTALL(TARGETS ${DOTNET_LAUNCHER_CORE} DESTINATION ${LIBDIR}) INSTALL(TARGETS ${DOTNET_LAUNCHER} DESTINATION ${BINDIR}) -INSTALL(TARGETS ${DOTNET_HYDRA_LAUNCHER} DESTINATION ${BINDIR}) +INSTALL(TARGETS ${DOTNET_LOADER} DESTINATION ${BINDIR}) +INSTALL(TARGETS ${DOTNET_CORERUN} DESTINATION ${BINDIR}) +INSTALL(TARGETS ${DOTNET_HYDRA_LOADER} DESTINATION ${BINDIR}) INSTALL(TARGETS ${TAC_COMMON} DESTINATION ${LIBDIR}) INSTALL(TARGETS ${NI_COMMON} DESTINATION ${LIBDIR}) INSTALL(TARGETS ${NITOOL} DESTINATION ${BINDIR}) diff --git a/NativeLauncher/dotnet.loader b/NativeLauncher/dotnet.loader index fbac563..3422bad 100644 --- a/NativeLauncher/dotnet.loader +++ b/NativeLauncher/dotnet.loader @@ -1,9 +1,9 @@ [LOADER] -NAME dotnet-launcher +NAME dotnet-loader # for candidate mode -EXE /usr/bin/dotnet-launcher +EXE /usr/bin/dotnet-loader # for hydra mode -#EXE /usr/bin/dotnet-hydra-launcher +#EXE /usr/bin/dotnet-hydra-loader APP_TYPE dotnet DETECTION_METHOD TIMEOUT|DEMAND TIMEOUT 5000 diff --git a/NativeLauncher/hydra/hydra_main.cc b/NativeLauncher/hydra/hydra_main.cc index 8312415..f446e36 100644 --- a/NativeLauncher/hydra/hydra_main.cc +++ b/NativeLauncher/hydra/hydra_main.cc @@ -27,7 +27,7 @@ #include "launcher_env.h" const char* __coreclr_lib = "/usr/share/dotnet.tizen/netcoreapp/libcoreclr.so"; -const char* __dotnet_launcher = "/usr/bin/dotnet-launcher"; +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); @@ -92,7 +92,7 @@ int main(int argc, char** argv) hydra_callback.fork = [](int argc, char **argv, void* user_data) -> int { _INFO("hydra : fork"); - void* launcher_h = dlopen(__dotnet_launcher, RTLD_NOW | RTLD_GLOBAL); + void* launcher_h = dlopen(__dotnet_loader, RTLD_NOW | RTLD_GLOBAL); if (launcher_h == nullptr) { _DBG("dlopen failed to open dotnet-launcher"); return -1; diff --git a/NativeLauncher/inc/log.h b/NativeLauncher/inc/log.h index 20f7d2f..bb0ca75 100644 --- a/NativeLauncher/inc/log.h +++ b/NativeLauncher/inc/log.h @@ -17,21 +17,12 @@ #ifndef __LOG_H__ #define __LOG_H__ -#ifndef NO_TIZEN #include #define LOGX(fmt, arg...) \ ({ do { \ dlog_print(DLOG_INFO, LOG_TAG, fmt, ##arg); \ } while (0); }) -#else -#include -#define LOGE(fmt, args...) printf(fmt, ##args) -#define LOGD(fmt, args...) printf(fmt, ##args) -#define LOGI(fmt, args...) printf(fmt, ##args) -#define LOGX(fmt, args...) printf(fmt, ##args) -#endif - #ifdef LOG_TAG #undef LOG_TAG #endif @@ -53,4 +44,12 @@ #define _LOGX(fmt, args...) LOGX(fmt "\n", ##args) #endif +#ifndef _SOUT +#define _SOUT(fmt, args...) fprintf(stdout, fmt "\n", ##args) +#endif + +#ifndef _SERR +#define _SERR(fmt, args...) fprintf(stderr, fmt "\n", ##args) +#endif + #endif /* __LOG_H__ */ diff --git a/NativeLauncher/inc/utils.h b/NativeLauncher/inc/utils.h index 3e8c154..b5c11b8 100644 --- a/NativeLauncher/inc/utils.h +++ b/NativeLauncher/inc/utils.h @@ -216,4 +216,17 @@ bool removeFile(const bf::path& path); */ bool removeAll(const bf::path& path); +/** + * @brief change command name of the current process for access via ps command + * @param[in] name + */ +void setCmdName(const char* name); + +/** + * @brief get file name from the path + * @param[in] file path + * @return return file name if exist otherwise null. + */ +char* getFileNameFromPath(char* path); + #endif /* __UTILS_H__ */ diff --git a/NativeLauncher/launcher/exec/corerun.cc b/NativeLauncher/launcher/exec/corerun.cc new file mode 100644 index 0000000..2a78bae --- /dev/null +++ b/NativeLauncher/launcher/exec/corerun.cc @@ -0,0 +1,66 @@ +/* + * 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 "dotnet_launcher.h" +#include "utils.h" +#include "log.h" + +using tizen::runtime::dotnetcore::CoreRuntime; + +int main(int argc, char *argv[]) +{ + _INFO("##### Run in corerun mode #####"); + + if (argc < 2) { + _SOUT("No parameter"); + return -1; + } + + if (!isManagedAssembly(argv[1]) && !isNativeImage(argv[1])) { + _SOUT("first parameter should be assembly file"); + return -1; + } + + // remove executable and assembly path form the arguments and pass that to managed code + int vargc = argc - 2; + std::vector vargs; + for (int i = 0; i < vargc; i++) { + vargs.push_back(argv[2 + i]); + } + + // set command name to assembly file + char* fileName = getFileNameFromPath(argv[1]); + setCmdName(fileName); + + CoreRuntime* runtime = new CoreRuntime("corerun"); + + // get absolute path of input dll file + std::string absoluteDllPath = absolutePath(argv[1]); + + if (runtime->initialize(LaunchMode::corerun, false, absoluteDllPath.c_str()) != 0) { + _SOUT("Failed to initialize"); + return -1; + } + + // launch application + if (runtime->launch(fileName, baseName(absoluteDllPath).c_str(), absoluteDllPath.c_str(), vargc, &vargs[0])) { + _SOUT("Failed to launch"); + return -1; + } + + return 0; +} + diff --git a/NativeLauncher/launcher/exec/launcher.cc b/NativeLauncher/launcher/exec/launcher.cc new file mode 100644 index 0000000..5a4ff57 --- /dev/null +++ b/NativeLauncher/launcher/exec/launcher.cc @@ -0,0 +1,107 @@ +/* + * 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 "dotnet_launcher.h" +#include "utils.h" +#include "log.h" + +#include +#include +#include + +#include +#include +#include + +#include + +using tizen::runtime::dotnetcore::CoreRuntime; + +// By the specification, application id must be shorter than 50 characters. +// Current length of argv[0] is 25 with a space. ("/usr/bin/dotnet-launcher ") +// To be able to change argv[0] when standalone mode padding for executable path is added. +#define APPID_MAX_LENGTH (25 + 105) +#define PRC_NAME_LENGTH 16 + +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"); + +int main(int argc, char *argv[]) +{ + _INFO("##### Run in standalone mode #####"); + + char* standalonePath = nullptr; + bool paddingExist = false; + const char* appRootPath = NULL; + char appId[APPID_MAX_LENGTH] = {0,}; + + std::vector vargs; + + // start index 1 to avoid passing executable name "dotnet-launcher" as a parameter + for (int i = 1; i < argc; i++) { + if (StandaloneOption.compare(argv[i]) == 0) { + if (i > argc - 1) { + _ERR("Assembly path must be after \"--standalone\" option"); + return -1; + } + i++; + standalonePath = argv[i]; + } else if (PaddingOption.compare(argv[i]) == 0) { + paddingExist = true; + } else { + vargs.push_back(argv[i]); + } + } + + CoreRuntime* runtime = new CoreRuntime("standalone"); + + // get app ID and app root path + if (AUL_R_OK == aul_app_get_appid_bypid(getpid(), appId, sizeof(appId))) { + _INFO("AUL_APPID : %s", appId); + // aul_get_app_root_path returns const char*, so there is no need to free after use. + appRootPath = aul_get_app_root_path(); + if (appRootPath == nullptr) { + _ERR("Fail to get application root path"); + return -1; + } + } else { + _ERR("Fail to get app_id"); + return -1; + } + + // set command name to assembly file + setCmdName(getFileNameFromPath(standalonePath)); + + // change cmdline from dotnet-launcher to executable path + int cmdlineSize = paddingExist ? APPID_MAX_LENGTH : APPID_MAX_LENGTH - PaddingOption.length(); + 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, true, appRootPath) != 0) { + _ERR("Failed to initialize"); + return -1; + } + + // launch application + if (runtime->launch(appId, appRootPath, standalonePath, vargs.size(), &vargs[0])) { + _ERR("Failed to launch"); + return -1; + } + + return 0; +} + diff --git a/NativeLauncher/launcher/exec/loader.cc b/NativeLauncher/launcher/exec/loader.cc new file mode 100644 index 0000000..c090fd9 --- /dev/null +++ b/NativeLauncher/launcher/exec/loader.cc @@ -0,0 +1,203 @@ +/* + * 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 "dotnet_launcher.h" +#include "utils.h" +#include "log.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +using tizen::runtime::dotnetcore::CoreRuntime; + +static Ecore_Fd_Handler *__fd_handler; +static loader_receiver_cb __receiver; + +// To precreate window(EFL/DALI), argc and argv should be passed. +// But, create callback of loader doesnot pass that to parameter. +// So, store argc and argv and use that to precreation. +// If window precreation code moves to managed, removed below code. +static int __argc; +static char **__argv; + +typedef struct AppInfo { + std::string root; + std::string app_path; + std::string appid; + std::string pkgid; +} AppInfo; +static AppInfo __appInfo; + + +//################## Code for running event loop for loader #################### + +static Eina_Bool __process_fd_handler(void *data, Ecore_Fd_Handler *handler) +{ + int fd; + + fd = ecore_main_fd_handler_fd_get(handler); + if (fd == -1) { + _ERR("[candidate] ECORE_FD_GET"); + exit(-1); + } + + if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ)) { + if (__receiver) + __receiver(fd); + } else if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR)) { + _ERR("[candidate] ECORE_FD_ERROR"); + close(fd); + exit(-1); + } + + return ECORE_CALLBACK_CANCEL; +} + +static void __adapter_loop_begin(void *user_data) +{ + ecore_main_loop_begin(); +} + +static void __adapter_loop_quit(void *user_data) +{ + ecore_main_loop_quit(); +} + +static void __adapter_add_fd(void *user_data, int fd, + loader_receiver_cb receiver) +{ + __fd_handler = ecore_main_fd_handler_add(fd, + static_cast(ECORE_FD_READ | ECORE_FD_ERROR), + __process_fd_handler, NULL, NULL, NULL); + + if (__fd_handler == NULL) { + _ERR("fd_handler is NULL"); + close(fd); + exit(-1); + } + + __receiver = receiver; +} + +static void __adapter_remove_fd(void *user_data, int fd) +{ + if (__fd_handler) { + ecore_main_fd_handler_del(__fd_handler); + __fd_handler = NULL; + __receiver = NULL; + } +} + +//################## Code for managing loader life-cycle ####################### + +static void __loader_create_cb(bundle *extra, int type, void *user_data) +{ + CoreRuntime* runtime = (CoreRuntime*)user_data; + + { + // do native window precreation here + } + + // initialize CoreRuntime (launchmode, dlog redirection enable, root path NULL) + if (runtime->initialize(LaunchMode::loader, true, NULL) != 0) { + _ERR("Failed to initialized"); + } else { + _INFO("Success to initialized"); + } +} + +static int __loader_launch_cb(int argc, char **argv, const char *app_path, + const char *appid, const char *pkgid, const char *pkg_type, + void *user_data) +{ + const char* root_path = aul_get_app_root_path(); + if (root_path != NULL) { + __appInfo.root = root_path; + } + + __appInfo.app_path = app_path; + __appInfo.appid = appid; + __appInfo.pkgid = pkgid; + + return 0; +} + +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(), + __appInfo.app_path.c_str(), argc - 1, argv + 1)) { + _ERR("Failed to launch"); + } + + return 0; +} + +//################## Main Code ################################################# + +extern "C" int realMain(int argc, char *argv[], const char* mode) +{ + _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")); + snprintf(argv[0], strlen("/usr/bin/dotnet-loader") + 1, + "/usr/bin/dotnet-loader"); + } + + setCmdName("dotnet-loader"); + + loader_lifecycle_callback_s callbacks = { + .create = __loader_create_cb, + .launch = __loader_launch_cb, + .terminate = __loader_terminate_cb + }; + + loader_adapter_s adapter = { + .loop_begin = __adapter_loop_begin, + .loop_quit = __adapter_loop_quit, + .add_fd = __adapter_add_fd, + .remove_fd = __adapter_remove_fd + }; + + return launchpad_loader_main(argc, argv, &callbacks, &adapter, runtime); +} + +int main(int argc, char *argv[]) +{ + __argc = argc; + __argv = argv; + + return realMain(argc, argv, "candidate"); +} + diff --git a/NativeLauncher/launcher/launcher.cc b/NativeLauncher/launcher/launcher.cc deleted file mode 100644 index 7af7576..0000000 --- a/NativeLauncher/launcher/launcher.cc +++ /dev/null @@ -1,236 +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 "launcher.h" -#include "log.h" - -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include - - -namespace tizen { -namespace runtime { - -struct FdHandler { - Ecore_Fd_Handler *handler; - loader_receiver_cb receiver; -}; - -static int __argc; -static char **__argv; - -class LaunchpadAdapterImpl : public LaunchpadAdapter -{ - public: - LaunchpadAdapterImpl() : - callbacks(), - adapter(), - __isLaunched(false) - { } - int loaderMain(int argc, char* argv[]) override; - - std::map handlers; - - private: - AppInfo appInfo; - loader_lifecycle_callback_s callbacks; - loader_adapter_s adapter; - bool __isLaunched; - std::string __launchPath; -}; - -LaunchpadAdapterImpl LaunchpadImpl; -LaunchpadAdapter& Launchpad = LaunchpadImpl; - -#define WITH_SELF(data) \ - LaunchpadAdapterImpl* self = static_cast(data); \ - if (self == nullptr) \ - _ERR("No LaunchpadImplData"); \ - else - -static Eina_Bool fdHandler(void *data, Ecore_Fd_Handler* handler) -{ - WITH_SELF(data) { - int fd = ecore_main_fd_handler_fd_get(handler); - if (fd == -1) { - _ERR("Failed to get the Ecore FD"); - exit(-1); - } - - if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ)) { - if (self->handlers.find(fd) != self->handlers.end()) - self->handlers[fd].receiver(fd); - } else if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR)) { - _ERR("Ecore FD Handler Have Error"); - close(fd); - exit(-1); - } - } - - return ECORE_CALLBACK_CANCEL; -} - -static void fdAdd(void *data, int fd, loader_receiver_cb receiver) -{ - Ecore_Fd_Handler* handler = ecore_main_fd_handler_add(fd, - static_cast(ECORE_FD_READ | ECORE_FD_ERROR), - fdHandler, data, nullptr, nullptr); - if (handler == nullptr) { - _ERR("Failed to add a FD handler to ecore main loop"); - close(fd); - exit(-1); - } WITH_SELF(data) { - self->handlers[fd] = {handler, receiver}; - } -} - -static void fdRemove(void *data, int fd) -{ - WITH_SELF(data) { - if (self->handlers.find(fd) != self->handlers.end()) { - Ecore_Fd_Handler* handler = self->handlers[fd].handler; - ecore_main_fd_handler_del(handler); - self->handlers.erase(fd); - } - } -} - -// To run dotnet-launcher on the headless device, remove build dependency from EFL. -#define ELEMENTARY_PATH "/usr/lib/libelementary.so.1" -static void* __win; -typedef int (*elm_init_ptr)(int argc, char **argv); -typedef void (*elm_config_accel_preference_set_ptr)(const char *pref); -typedef void* (*elm_win_add_ptr)(void* parent, const char* name, int type); -typedef void (*elm_win_precreated_object_set_ptr)(void* win); - -static void preCreateWindow() -{ - struct stat sb; - if (stat(ELEMENTARY_PATH, &sb) != 0) { - _ERR("[candidate] libelementary is not exist. skip precreation"); - return; - } - - int elmInitCnt = 0; - void* handle = nullptr; - elm_init_ptr elm_init = nullptr; - elm_config_accel_preference_set_ptr elm_config_accel_preference_set = nullptr; - elm_win_add_ptr elm_win_add = nullptr; - elm_win_precreated_object_set_ptr elm_win_precreated_object_set = nullptr; - - handle = dlopen(ELEMENTARY_PATH, RTLD_NOW | RTLD_GLOBAL); - if (handle) { - elm_init = (elm_init_ptr)dlsym(handle, "elm_init"); - if (elm_init) { - elmInitCnt = elm_init(__argc, __argv); - - if (!elmInitCnt) { - _ERR("[candidate] elm_init() failed"); - return; - } - } - - elm_config_accel_preference_set = (elm_config_accel_preference_set_ptr)dlsym(handle, "elm_config_accel_preference_set"); - if (elm_config_accel_preference_set) { - elm_config_accel_preference_set("hw"); - } - - elm_win_add = (elm_win_add_ptr)dlsym(handle, "elm_win_add"); - if (elm_win_add) { - // enum value of "ELM_WIN_BASIC" is 0 - __win = elm_win_add(NULL, "package_name", 0); - if (__win == NULL) { - _ERR("[candidate] elm_win_add() failed"); - return; - } - } - - elm_win_precreated_object_set = (elm_win_precreated_object_set_ptr)dlsym(handle, "elm_win_precreated_object_set"); - if (elm_win_precreated_object_set) { - elm_win_precreated_object_set(__win); - } - _INFO("elm window precreation is done"); - } -} - -int LaunchpadAdapterImpl::loaderMain(int argc, char* argv[]) -{ - __argc = argc; - __argv = argv; - callbacks.create = [](bundle *extra, int type, void *userData) { - preCreateWindow(); - WITH_SELF(userData) { - if (self->onCreate != nullptr) - self->onCreate(); - } - }; - callbacks.launch = [](int argc, char** argv, const char* appPath, - const char* appId, const char* pkgId, - const char* pkgType, void* userData) -> int { - WITH_SELF(userData) { - const char* appRootPath = aul_get_app_root_path(); - if (appRootPath != nullptr) { - self->appInfo.root = std::string(appRootPath); - } - self->appInfo.path = appPath; - self->appInfo.id = appId; - self->appInfo.pkg = pkgId; - self->appInfo.type = pkgType; - if (self->onLaunch != nullptr) - self->onLaunch(self->appInfo, argc, argv); - } - - return 0; - }; - callbacks.terminate = [](int argc, char **argv, void* userData) -> int { - WITH_SELF(userData) { - if (self->onTerminate != nullptr) - self->onTerminate(self->appInfo, argc, argv); - } - return 0; - }; - - adapter.loop_begin = [](void *data) { - ecore_main_loop_begin(); - }; - - adapter.loop_quit = [](void *data) { - ecore_main_loop_quit(); - }; - adapter.add_fd = fdAdd; - adapter.remove_fd = fdRemove; - - _INFO("launchpad_loader_main is start"); - int r = launchpad_loader_main(argc, argv, &(this->callbacks), &(this->adapter), this); - _INFO("launchpad_loader_main is finished with [%d]", r); - - return r; -} - -#undef WITH_SELF - -} // namespace runtime -} // namespace tizen diff --git a/NativeLauncher/launcher/launcher.h b/NativeLauncher/launcher/launcher.h deleted file mode 100644 index e48f318..0000000 --- a/NativeLauncher/launcher/launcher.h +++ /dev/null @@ -1,48 +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 __LAUNCHER_INTERFACE_H__ -#define __LAUNCHER_INTERFACE_H__ - -#include -#include - -namespace tizen { -namespace runtime { - -struct AppInfo { - std::string root; - std::string path; - std::string id; - std::string pkg; - std::string type; -}; - -class LaunchpadAdapter -{ - public: - virtual int loaderMain(int argc, char* argv[]) = 0; - std::function onCreate = nullptr; - std::function onLaunch = nullptr; - std::function onTerminate = nullptr; -}; - -extern LaunchpadAdapter& Launchpad; - -} // namespace runtime -} // namespace tizen - -#endif /* __LAUNCHER_INTERFACE_H__ */ diff --git a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc b/NativeLauncher/launcher/lib/dotnet_launcher.cc similarity index 98% rename from NativeLauncher/launcher/dotnet/dotnet_launcher.cc rename to NativeLauncher/launcher/lib/dotnet_launcher.cc index 650d5b7..c900ef2 100644 --- a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc +++ b/NativeLauncher/launcher/lib/dotnet_launcher.cc @@ -42,7 +42,6 @@ #include "injection.h" #include "utils.h" #include "log.h" -#include "launcher.h" #include "dotnet_launcher.h" #include "plugin_manager.h" #include "path_manager.h" @@ -349,7 +348,7 @@ CoreRuntime::~CoreRuntime() dispose(); } -int CoreRuntime::initialize(bool standalone, bool useDlog, const char* corerunRoot) +int CoreRuntime::initialize(LaunchMode launchMode, bool useDlog, const char* rootPath) { // checkInjection checks dotnet-launcher run mode // At the moment, this mechanism is used only when the Memory Profiler is started. @@ -383,7 +382,7 @@ int CoreRuntime::initialize(bool standalone, bool useDlog, const char* corerunRo #endif // __arm__ // Disable debug pipes and semaphores creation in case of non-standlone mode - if (!standalone) + if (launchMode == LaunchMode::loader) putenv(const_cast("COMPlus_EnableDiagnostics=0")); // Write Debug.WriteLine to stderr @@ -437,7 +436,7 @@ int CoreRuntime::initialize(bool standalone, bool useDlog, const char* corerunRo _INFO("libcoreclr dlopen and dlsym success"); - if (!standalone) { + if (launchMode == LaunchMode::loader) { pluginPreload(); // terminate candidate process if language is changed. @@ -458,10 +457,10 @@ int CoreRuntime::initialize(bool standalone, bool useDlog, const char* corerunRo std::string NIprobePath; std::string nativeLibPath; - if (corerunRoot) { - probePath = corerunRoot; - NIprobePath = corerunRoot; - nativeLibPath = corerunRoot; + if (launchMode == LaunchMode::corerun) { + probePath = rootPath; + NIprobePath = rootPath; + nativeLibPath = rootPath; } else { __fd = open("/proc/self", O_DIRECTORY); if (__fd < 0) { @@ -490,7 +489,7 @@ int CoreRuntime::initialize(bool standalone, bool useDlog, const char* corerunRo __initialized = true; - if (!standalone) { + if (launchMode == LaunchMode::loader) { preloadTypes(); // Preload common managed code } diff --git a/NativeLauncher/launcher/dotnet/dotnet_launcher.h b/NativeLauncher/launcher/lib/dotnet_launcher.h similarity index 92% rename from NativeLauncher/launcher/dotnet/dotnet_launcher.h rename to NativeLauncher/launcher/lib/dotnet_launcher.h index f5cedc9..8f6c22a 100644 --- a/NativeLauncher/launcher/dotnet/dotnet_launcher.h +++ b/NativeLauncher/launcher/lib/dotnet_launcher.h @@ -17,10 +17,17 @@ #ifndef __DOTNET_LAUNCHER_H__ #define __DOTNET_LAUNCHER_H__ -#include "launcher.h" +#include + #include "coreclr_host.h" #include "plugin_manager.h" +enum LaunchMode { + corerun = 0, + loader, + launcher +}; + namespace tizen { namespace runtime { namespace dotnetcore { @@ -30,12 +37,11 @@ class CoreRuntime public: CoreRuntime(const char* mode); ~CoreRuntime(); - int initialize(bool standalone, bool useDlog, const char* corerunRoot); + int initialize(LaunchMode mode, bool useDlog, const char* rootPath); 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 preloadTypes(); coreclr_initialize_ptr initializeClr; diff --git a/NativeLauncher/launcher/injection.cc b/NativeLauncher/launcher/lib/injection.cc similarity index 100% rename from NativeLauncher/launcher/injection.cc rename to NativeLauncher/launcher/lib/injection.cc diff --git a/NativeLauncher/launcher/injection.h b/NativeLauncher/launcher/lib/injection.h similarity index 100% rename from NativeLauncher/launcher/injection.h rename to NativeLauncher/launcher/lib/injection.h diff --git a/NativeLauncher/launcher/main.cc b/NativeLauncher/launcher/main.cc deleted file mode 100644 index 42ca9f4..0000000 --- a/NativeLauncher/launcher/main.cc +++ /dev/null @@ -1,170 +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 "dotnet/dotnet_launcher.h" -#include "utils.h" -#include "log.h" - -#include -#include -#include - -#include -#include -#include -#include - -// By the specification, application id must be shorter than 50 characters. -// Current length of argv[0] is 25 with a space. ("/usr/bin/dotnet-launcher ") -// To be able to change argv[0] when standalone mode padding for executable path is added. -#define APPID_MAX_LENGTH (25 + 105) - -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"); - -extern "C" int realMain(int argc, char *argv[], const char* mode) -{ - int i; - bool standaloneMode = false; - char* standalonePath = nullptr; - bool corerunMode = false; - bool paddingExist = false; - - std::vector vargs; - - // start index 1 to avoid passing executable name "dotnet-launcher" as a parameter - for (i = 1; i < argc; i++) { - if (StandaloneOption.compare(argv[i]) == 0) { - standaloneMode = true; - - if (i > argc - 1) { - fprintf(stderr, "Assembly path must be after \"--standalone\" option\n"); - return 1; - } - i++; - standalonePath = argv[i]; - } else if (PaddingOption.compare(argv[i]) == 0) { - paddingExist = true; - } else { - vargs.push_back(argv[i]); - } - } - - if (isManagedAssembly(argv[1]) || isNativeImage(argv[1])) { - corerunMode = true; - } - - using tizen::runtime::Launchpad; - using tizen::runtime::AppInfo; - using tizen::runtime::dotnetcore::CoreRuntime; - - std::unique_ptr runtime(new CoreRuntime(mode)); - - if (corerunMode) { - _INFO("##### Run in corerun mode #####"); - char appId[APPID_MAX_LENGTH] = {0,}; - std::string appRoot; - snprintf(appId, 16, "%s", "dotnet-launcher"); - std::string absoluteDllPath = absolutePath(argv[1]); - appRoot = baseName(absoluteDllPath); - - if (runtime->initialize(true, false, appRoot.c_str()) != 0) { - _ERR("Failed to initialize"); - return 1; - } - - int argsLen = vargs.size() - 1; - char** args = &vargs[1]; - if (runtime->launch(appId, appRoot.c_str(), absoluteDllPath.c_str(), argsLen, args)) { - _ERR("Failed to launch"); - return 1; - } - } else if (standaloneMode) { - _INFO("##### Run in standalone mode #####"); - char appId[APPID_MAX_LENGTH] = {0,}; - std::string appRoot; - if (AUL_R_OK == aul_app_get_appid_bypid(getpid(), appId, sizeof(appId))) { - const char* appRootPath = aul_get_app_root_path(); - if (appRootPath != nullptr) - appRoot = std::string(appRootPath); - } else { - // If appId is not set, it is executed directly by cmdline. - // In this case, appRoot is passed as an argument. - snprintf(appId, 16, "%s", "dotnet-launcher"); - appRoot = baseName(baseName(standalonePath)); - } - _INFO("AUL_APPID : %s", appId); - - if (runtime->initialize(true, true, NULL) != 0) { - _ERR("Failed to initialize"); - return 1; - } - - // change cmdline from dotnet-launcher to executable path - int cmdlineSize = paddingExist ? APPID_MAX_LENGTH : APPID_MAX_LENGTH - PaddingOption.length(); - memset(argv[0], '\0', cmdlineSize); - snprintf(argv[0], cmdlineSize, "%s", standalonePath); - - int argsLen = vargs.size(); - char** args = &vargs[0]; - if (runtime->launch(appId, appRoot.c_str(), standalonePath, argsLen, args)) { - _ERR("Failed to launch"); - return 1; - } - } else { - // change cmdline from dotnet-hydra-launcher to dotnet-launcher - if (strcmp(argv[0], "/usr/bin/dotnet-hydra-launcher") == 0) { - memset(argv[0], '\0', strlen("/usr/bin/dotnet-hydra-launcher")); - snprintf(argv[0], strlen("/usr/bin/dotnet-launcher") + 1, "/usr/bin/dotnet-launcher"); - } - - Launchpad.onCreate = [&runtime]() { - if (runtime->initialize(false, true, NULL) != 0) { - _ERR("Failed to initialized"); - } else { - _INFO("Success to initialized"); - } - }; - - Launchpad.onTerminate = [&runtime](const AppInfo& appInfo, int argc, char** argv) { - _INFO("launch request with app path : %s", appInfo.path.c_str()); - _INFO("appId : %s", appInfo.id.c_str()); - _INFO("pkg : %s", appInfo.pkg.c_str()); - - // aul_get_app_root_path() can return NULL for error case. - if (appInfo.root.empty()) { - _ERR("Failed to launch. root path is set to NULL"); - } else { - // 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.id.c_str(), appInfo.root.c_str(), appInfo.path.c_str(), argc-1, argv+1)) - _ERR("Failed to launch"); - } - }; - int ret = Launchpad.loaderMain(argc, argv); - if (ret < 0) { - _ERR("fail to start loaderMain. candidate process is not created."); - return 1; - } - } - - return 0; -} - -int main(int argc, char *argv[]) -{ - return realMain(argc, argv, "default"); -} diff --git a/NativeLauncher/util/utils.cc b/NativeLauncher/util/utils.cc index 2c29518..014f760 100644 --- a/NativeLauncher/util/utils.cc +++ b/NativeLauncher/util/utils.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -596,3 +597,29 @@ bool removeAll(const bf::path& path) { } return true; } + +void setCmdName(const char* name) +{ + #define PRC_NAME_LENGTH 16 + + char processName[PRC_NAME_LENGTH] = {0, }; + + if (name == NULL || *name == '\0') { + return; + } + + memset(processName, '\0', PRC_NAME_LENGTH); + snprintf(processName, PRC_NAME_LENGTH, "%s", name); + prctl(PR_SET_NAME, processName); +} + +char* getFileNameFromPath(char* path) +{ + char* fileName = strrchr(path, PATH_SEPARATOR); + if (fileName != NULL && *fileName != '\0') { + return ++fileName; + } + + return NULL; +} + diff --git a/dotnet-launcher.manifest b/dotnet-launcher.manifest index 0f2e9fc..e14cc1f 100644 --- a/dotnet-launcher.manifest +++ b/dotnet-launcher.manifest @@ -4,5 +4,7 @@ + + diff --git a/packaging/dotnet-launcher.spec b/packaging/dotnet-launcher.spec index a77161e..e1fd6b1 100644 --- a/packaging/dotnet-launcher.spec +++ b/packaging/dotnet-launcher.spec @@ -142,6 +142,9 @@ install -m 0644 %{name}.conf %{buildroot}/etc/tmpfiles.d/%{name}.conf mkdir -p /opt/etc/skel/.dotnet chsmack -t -a User::App::Shared /opt/etc/skel/.dotnet %{_bindir}/dotnettool --ni-dll %{_runtime_dir}/System.Private.CoreLib.dll +setcap cap_setgid,cap_sys_admin+ei /usr/bin/dotnet-launcher +setcap cap_setgid,cap_sys_admin+ei /usr/bin/dotnet-loader +setcap cap_setgid,cap_sys_admin+ei /usr/bin/dotnet %files %manifest dotnet-launcher.manifest @@ -156,8 +159,11 @@ chsmack -t -a User::App::Shared /opt/etc/skel/.dotnet %{_install_mdplugin_dir}/libprefer_nuget_cache_plugin.so %{_install_mdplugin_dir}/libprefer_dotnet_aot_plugin.so %{_bindir}/dotnet-launcher -%{_bindir}/dotnet-hydra-launcher +%{_bindir}/dotnet-loader +%{_bindir}/dotnet +%{_bindir}/dotnet-hydra-loader %{_libdir}/libdotnet_launcher_util.so +%{_libdir}/libdotnet_launcher_core.so %{_libdir}/libni_common.so %{_libdir}/libtac_common.so /etc/tmpfiles.d/%{name}.conf -- 2.7.4