From 4fdf300081e1e2026ea8a438a82167a174237ab8 Mon Sep 17 00:00:00 2001 From: "j-h.choi" Date: Tue, 8 May 2018 12:22:47 +0900 Subject: [PATCH 01/16] [Coverity-112249] Fixed coverity issue. (NEGATIVE_RETURNS) Change-Id: I9810f00e9647010ee5a948ef4d07877fd8fbbdbb --- NativeLauncher/launcher/dotnet/dotnet_launcher.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc index db5c2c5..f3a1056 100644 --- a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc +++ b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc @@ -339,7 +339,8 @@ int CoreRuntime::launch(const char* appId, const char* root, const char* path, i int fd2 = open(root, O_DIRECTORY); dup3(fd2, fd, O_CLOEXEC); - close(fd2); + if (fd2 >= 0) + close(fd2); if (pluginBeforeExecute) pluginBeforeExecute(); -- 2.7.4 From 2a33f41b1d75db97a25b823dcc3cbb8f11713157 Mon Sep 17 00:00:00 2001 From: Cho Woong Suk Date: Fri, 25 May 2018 12:58:52 +0900 Subject: [PATCH 02/16] add --r2r option for nitool to test ready-to-run feature of coreclr 2.1 Change-Id: I2e5afc8cf0b64fb6627df196c0325607c22c401a --- NativeLauncher/installer-plugin/common.cc | 51 ++++++++++++---------- NativeLauncher/installer-plugin/common.h | 12 ++--- NativeLauncher/installer-plugin/nitool.cc | 14 ++++-- .../installer-plugin/prefer_dotnet_aot_plugin.cc | 2 +- 4 files changed, 46 insertions(+), 33 deletions(-) diff --git a/NativeLauncher/installer-plugin/common.cc b/NativeLauncher/installer-plugin/common.cc index 3ab426c..31596f4 100644 --- a/NativeLauncher/installer-plugin/common.cc +++ b/NativeLauncher/installer-plugin/common.cc @@ -102,7 +102,7 @@ static void smack_(const char* dllPath, const char* label) } } -static void crossgen(const char* dllPath, const char* appPath) +static void crossgen(const char* dllPath, const char* appPath, bool enableR2R) { //pid_t parent = getpid(); pid_t pid = fork(); @@ -148,9 +148,16 @@ static void crossgen(const char* dllPath, const char* appPath) std::vector argv = { __CROSSGEN_PATH, "/Trusted_Platform_Assemblies", tpa.c_str(), - "/JITPath", __JIT_PATH, - "/FragileNonVersionable" + "/JITPath", __JIT_PATH }; + + if (!enableR2R) { + fprintf(stderr, "FNV mode enabled!!!\n"); + argv.push_back("/FragileNonVersionable"); + } else { + fprintf(stderr, "R2R mode enabled!!!\n"); + } + if (appPath != nullptr) { argv.push_back("/App_Paths"); argv.push_back(appPath); @@ -245,7 +252,8 @@ static int appAotCb(pkgmgrinfo_appinfo_h handle, void *userData) } // When you create native image with pkgid, ni file is generated even though already ni file exist. - if (createNiUnderPkgRoot(pkgId) != 0) { + // Regenerate ni files with R2R mode forcibiliy. (there is no way to now which option is used) + if (createNiUnderPkgRoot(pkgId, true) != 0) { _ERR("Failed to get root path from [%s]", pkgId); return -1; } else { @@ -283,14 +291,14 @@ int regenerateAppNI() return 0; } -static void createCoreLibNI() +static void createCoreLibNI(bool enableR2R) { std::string coreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll"); std::string niCoreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.ni.dll"); std::string coreLibBackup = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll.Backup"); if (!niExist(coreLib, niCoreLib)) { - crossgen(coreLib.c_str(), nullptr); + crossgen(coreLib.c_str(), nullptr, enableR2R); if (!fileNotExist(niCoreLib)) { // change owner and groups for generated ni file. struct stat info; @@ -321,7 +329,6 @@ void removeNiUnderDirs(const char* rootPaths[], int count) void removeNiPlatform() { std::string coreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll"); - std::string niCoreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.ni.dll"); std::string coreLibBackup = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll.Backup"); if (fileNotExist(coreLibBackup)) { @@ -339,25 +346,25 @@ void removeNiPlatform() removeNiUnderDirs(platformDirs, 3); } -void createNiPlatform() +void createNiPlatform(bool enableR2R) { - createCoreLibNI(); + createCoreLibNI(enableR2R); const char* platformDirs[] = {__RUNTIME_DIR, __DEVICE_API_DIR, "/usr/bin"}; createNiUnderDirs(platformDirs, 3, [](const char* ni) { smack_(ni, "_"); - }, false); + }, enableR2R); } -void createNiSelect(const char* dllPath) +void createNiSelect(const char* dllPath, bool enableR2R) { - createCoreLibNI(); + createCoreLibNI(enableR2R); std::string niPath; if (!fileNotExist(dllPath)) { if (!niExist(dllPath, niPath)) { - crossgen(dllPath, nullptr); + crossgen(dllPath, nullptr, enableR2R); if (niExist(dllPath, niPath)) { // change owner and groups for generated ni file. struct stat info; @@ -375,7 +382,7 @@ void createNiSelect(const char* dllPath) } } -void createNiUnderDirs(const char* rootPaths[], int count, const char* ignores[], int igcount, afterCreate cb, bool update) +void createNiUnderDirs(const char* rootPaths[], int count, const char* ignores[], int igcount, afterCreate cb, bool update, bool enableR2R) { std::string appPaths; for (int i = 0; i < count; i++) { @@ -386,7 +393,7 @@ void createNiUnderDirs(const char* rootPaths[], int count, const char* ignores[] if (appPaths.back() == ':') appPaths.pop_back(); - auto convert = [&appPaths, ignores, igcount, &cb, update](const char* path, const char* name) { + auto convert = [&appPaths, ignores, igcount, &cb, update, enableR2R](const char* path, const char* name) { for (int i = 0; i < igcount; i++) { if (strcmp(path, ignores[i]) == 0) return; @@ -401,7 +408,7 @@ void createNiUnderDirs(const char* rootPaths[], int count, const char* ignores[] return; } } - crossgen(path, appPaths.c_str()); + crossgen(path, appPaths.c_str(), enableR2R); if (niExist(path, niPath)) { // change owner and groups for generated ni file. struct stat info; @@ -421,13 +428,13 @@ void createNiUnderDirs(const char* rootPaths[], int count, const char* ignores[] for (int i = 0; i < count; i++) scanFilesInDir(rootPaths[i], convert, 1); } -void createNiUnderDirs(const char* rootPaths[], int count, afterCreate cb, bool update) +void createNiUnderDirs(const char* rootPaths[], int count, afterCreate cb, bool update, bool enableR2R) { - createNiUnderDirs(rootPaths, count, nullptr, 0, cb, update); + createNiUnderDirs(rootPaths, count, nullptr, 0, cb, update, enableR2R); } -void createNiUnderDirs(const char* rootPaths[], int count, bool update) +void createNiUnderDirs(const char* rootPaths[], int count, bool update, bool enableR2R) { - createNiUnderDirs(rootPaths, count, nullptr, update); + createNiUnderDirs(rootPaths, count, nullptr, update, enableR2R); } int removeNiUnderPkgRoot(const char* pkgName) @@ -452,7 +459,7 @@ int removeNiUnderPkgRoot(const char* pkgName) } -int createNiUnderPkgRoot(const char* pkgName) +int createNiUnderPkgRoot(const char* pkgName, bool enableR2R) { std::string pkgRoot; if (getRootPath(pkgName, pkgRoot) < 0) @@ -487,7 +494,7 @@ int createNiUnderPkgRoot(const char* pkgName) _INFO("sleep %d usec", interval); usleep(interval); } - }, true); + }, true, enableR2R); return 0; } diff --git a/NativeLauncher/installer-plugin/common.h b/NativeLauncher/installer-plugin/common.h index 26fe0ee..325bb82 100644 --- a/NativeLauncher/installer-plugin/common.h +++ b/NativeLauncher/installer-plugin/common.h @@ -21,12 +21,12 @@ typedef std::function afterCreate; int regenerateAppNI(); -void createNiUnderDirs(const char* rootPaths[], int count, const char* ignores[], int igcount, afterCreate cb, bool update); -void createNiUnderDirs(const char* rootPaths[], int count, afterCreate cb, bool update); -void createNiUnderDirs(const char* rootPaths[], int count, bool update); -int createNiUnderPkgRoot(const char* pkgName); -void createNiPlatform(); -void createNiSelect(const char* dllPath); +void createNiUnderDirs(const char* rootPaths[], int count, const char* ignores[], int igcount, afterCreate cb, bool update, bool enableR2R); +void createNiUnderDirs(const char* rootPaths[], int count, afterCreate cb, bool update, bool enableR2R); +void createNiUnderDirs(const char* rootPaths[], int count, bool update, bool enableR2R); +int createNiUnderPkgRoot(const char* pkgName, bool enableR2R); +void createNiPlatform(bool enableR2R); +void createNiSelect(const char* dllPath, bool enableR2R); void removeNiPlatform(); int removeNiUnderPkgRoot(const char* pkgName); diff --git a/NativeLauncher/installer-plugin/nitool.cc b/NativeLauncher/installer-plugin/nitool.cc index 989fb42..bb996af 100644 --- a/NativeLauncher/installer-plugin/nitool.cc +++ b/NativeLauncher/installer-plugin/nitool.cc @@ -46,6 +46,7 @@ static void help(const char *argv0) " --dll - Create NI for DLL\n" " --pkg - Create NI for package\n" " --dir - Create NI for directory\n" + " --r2r - Use ready-to-run option (default: FNV)\n" " --reset-system - Remove System NI files\n" " --reset-pkg - Remove App NI files\n" " --regen-all-app - Re-generate All App NI files\n" @@ -66,12 +67,17 @@ int main(int argc, char* argv[]) bool dllMode = false; bool dirMode = false; bool rmPkgMode = false; + bool enableR2R = false; + + if (cmdOptionExists(argv, argv+argc, "--r2r")) { + enableR2R = true; + } if (cmdOptionExists(argv, argv+argc, "--help")) { help(argv[0]); return 0; } else if (cmdOptionExists(argv, argv+argc, "--system")) { - createNiPlatform(); + createNiPlatform(enableR2R); return 0; } else if (cmdOptionExists(argv, argv+argc, "--dll")) { dllMode = true; @@ -105,7 +111,7 @@ int main(int argc, char* argv[]) if (pkgMode) { for (const char* pkg : args) { - if (createNiUnderPkgRoot(pkg) != 0) { + if (createNiUnderPkgRoot(pkg, enableR2R) != 0) { fprintf(stderr, "Failed to get root path from [%s]\n", pkg); return 1; } @@ -119,9 +125,9 @@ int main(int argc, char* argv[]) } } else if (dllMode) { for (const char* dll : args) - createNiSelect(dll); + createNiSelect(dll, enableR2R); } else if (dirMode) { - createNiUnderDirs(args.data(), args.size(), false); + createNiUnderDirs(args.data(), args.size(), false, enableR2R); } return 0; diff --git a/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc b/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc index 83a018e..d7fd274 100644 --- a/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc +++ b/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc @@ -51,7 +51,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app } if (mdValue) { - if (createNiUnderPkgRoot(pkgId) != 0) { + if (createNiUnderPkgRoot(pkgId, false) != 0) { _ERR("Failed to get root path from [%s]", pkgId); return -1; } else { -- 2.7.4 From a2f06cd0f3590bad3a7298309091143821dc83ef Mon Sep 17 00:00:00 2001 From: Woongsuk Cho Date: Mon, 11 Jun 2018 11:25:46 +0900 Subject: [PATCH 03/16] use lldb-mi for debugging Change-Id: I0c4b39efffaa60804f44f343ae14d3c35e79b25d --- NativeLauncher/dotnet.debugger | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NativeLauncher/dotnet.debugger b/NativeLauncher/dotnet.debugger index 7a89927..11d28d3 100644 --- a/NativeLauncher/dotnet.debugger +++ b/NativeLauncher/dotnet.debugger @@ -5,3 +5,10 @@ APP_TYPE dotnet EXTRA_KEY __DLP_DEBUG_ARG__ EXTRA_ENV CORECLR_GDBJIT EXTRA_ENV COMPlus_ZapDisable + +[DEBUGGER] +NAME LLDB-MI +EXE /opt/usr/home/owner/share/tmp/sdk_tools/lldb/bin/lldb-mi +APP_TYPE dotnet +EXTRA_KEY __DLP_ATTACH_ARG__ +ATTACH true -- 2.7.4 From 15a960a952c2068cc59335be805e45d2dc792346 Mon Sep 17 00:00:00 2001 From: Igor Kulaychuk Date: Mon, 16 Apr 2018 18:01:00 +0300 Subject: [PATCH 04/16] Enable launch under netcoredbg Change-Id: I0c856827f1daa0d0e9ef6e6534439d3766c88a51 --- NativeLauncher/dotnet.debugger | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NativeLauncher/dotnet.debugger b/NativeLauncher/dotnet.debugger index 11d28d3..9b2cb71 100644 --- a/NativeLauncher/dotnet.debugger +++ b/NativeLauncher/dotnet.debugger @@ -12,3 +12,9 @@ EXE /opt/usr/home/owner/share/tmp/sdk_tools/lldb/bin/lldb-mi APP_TYPE dotnet EXTRA_KEY __DLP_ATTACH_ARG__ ATTACH true + +[DEBUGGER] +NAME NETCOREDBG +EXE /home/owner/share/tmp/sdk_tools/netcoredbg/netcoredbg +APP_TYPE dotnet +EXTRA_KEY __DLP_DEBUG_ARG__ -- 2.7.4 From 639e23e19bc3cfb7833f7d8379262cc52c23bd95 Mon Sep 17 00:00:00 2001 From: Woongsuk Cho Date: Wed, 27 Jun 2018 11:23:14 +0900 Subject: [PATCH 05/16] Refactoring dotnet-launcher - remove unused code - use std::string instead of char* to reduce human failure - remove LauncherInterface - create path manager and plugin manager - provide AOT functionality to external - dev package support - some AOT functionality is added (dlls under package root) Change-Id: I26972910324b60174cc2cf3ff6ec28da4a2fcd18 --- NativeLauncher/CMakeLists.txt | 70 +-- NativeLauncher/dotnet-launcher.pc.in | 9 + NativeLauncher/inc/coreclr_host.h | 52 +++ NativeLauncher/inc/dotnet_launcher_plugin.h | 38 ++ NativeLauncher/inc/plugin_manager.h | 50 +++ NativeLauncher/inc/utils.h | 23 +- NativeLauncher/installer-plugin/common.cc | 500 --------------------- NativeLauncher/installer-plugin/common.h | 33 -- NativeLauncher/installer-plugin/ni_common.cc | 486 ++++++++++++++++++++ NativeLauncher/installer-plugin/ni_common.h | 127 ++++++ NativeLauncher/installer-plugin/nitool.cc | 42 +- .../installer-plugin/prefer_dotnet_aot_plugin.cc | 8 +- NativeLauncher/installer-plugin/ui-application.cc | 2 +- NativeLauncher/launcher/dotnet/dotnet_launcher.cc | 165 ++----- NativeLauncher/launcher/dotnet/dotnet_launcher.h | 78 +--- NativeLauncher/launcher/launcher.cc | 26 +- NativeLauncher/launcher/launcher.h | 8 - NativeLauncher/launcher/main.cc | 23 +- NativeLauncher/util/path_manager.cc | 138 ++++++ NativeLauncher/util/path_manager.h | 30 ++ NativeLauncher/util/plugin_manager.cc | 105 +++++ NativeLauncher/util/utils.cc | 174 ++----- packaging/dotnet-launcher.spec | 29 +- 23 files changed, 1240 insertions(+), 976 deletions(-) create mode 100644 NativeLauncher/dotnet-launcher.pc.in create mode 100644 NativeLauncher/inc/coreclr_host.h create mode 100644 NativeLauncher/inc/dotnet_launcher_plugin.h create mode 100644 NativeLauncher/inc/plugin_manager.h delete mode 100644 NativeLauncher/installer-plugin/common.cc delete mode 100644 NativeLauncher/installer-plugin/common.h create mode 100644 NativeLauncher/installer-plugin/ni_common.cc create mode 100644 NativeLauncher/installer-plugin/ni_common.h create mode 100644 NativeLauncher/util/path_manager.cc create mode 100644 NativeLauncher/util/path_manager.h create mode 100644 NativeLauncher/util/plugin_manager.cc diff --git a/NativeLauncher/CMakeLists.txt b/NativeLauncher/CMakeLists.txt index 98d60c8..b53ec6f 100644 --- a/NativeLauncher/CMakeLists.txt +++ b/NativeLauncher/CMakeLists.txt @@ -3,12 +3,8 @@ PROJECT("dotnet-tools") MESSAGE("CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") -IF(DEFINED NO_TIZEN) - SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DNO_TIZEN") -ELSE(DEFINED NO_TIZEN) - INCLUDE(FindPkgConfig) - PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED aul pkgmgr-info pkgmgr-installer dlog ecore bundle dlog launchpad elementary glib-2.0) -ENDIF(DEFINED NO_TIZEN) +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED aul pkgmgr-info pkgmgr-installer dlog ecore bundle dlog launchpad elementary glib-2.0 libsmack) FOREACH(flag ${${PROJECT_NAME}_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") @@ -68,35 +64,45 @@ SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") INCLUDE_DIRECTORIES(inc launcher util) +SET(DOTNET_LAUNCHER_UTIL "dotnet_launcher_util") +SET(${DOTNET_LAUNCHER_UTIL}_SOURCE_FILES + util/utils.cc + util/plugin_manager.cc + util/path_manager.cc +) +ADD_LIBRARY(${DOTNET_LAUNCHER_UTIL} SHARED ${${DOTNET_LAUNCHER_UTIL}_SOURCE_FILES}) +SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER_UTIL} PROPERTIES COMPILE_FLAGS "-fPIC") +TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER_UTIL} ${${PROJECT_NAME}_LDFLAGS}) + SET(DOTNET_LAUNCHER "dotnet-launcher") SET(${DOTNET_LAUNCHER}_SOURCE_FILES launcher/main.cc - util/utils.cc launcher/launcher.cc launcher/dotnet/dotnet_launcher.cc ) ADD_EXECUTABLE(${DOTNET_LAUNCHER} ${${DOTNET_LAUNCHER}_SOURCE_FILES}) SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER} PROPERTIES COMPILE_FLAGS "-fPIE") - - -IF(NOT DEFINED NO_TIZEN) - TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} aul) -ENDIF(NOT DEFINED NO_TIZEN) -TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl -lpthread") +TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl -lpthread" aul ${DOTNET_LAUNCHER_UTIL}) SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER} PROPERTIES SKIP_BUILD_RPATH TRUE ) # remove rpath option that is automatically generated by cmake. +SET(NI_COMMON "ni_common") +SET(${NI_COMMON}_SOURCE_FILES + installer-plugin/ni_common.cc +) +ADD_LIBRARY(${NI_COMMON} SHARED ${${NI_COMMON}_SOURCE_FILES}) +SET_TARGET_PROPERTIES(${NI_COMMON} PROPERTIES COMPILE_FLAGS "-fPIC") +TARGET_LINK_LIBRARIES(${NI_COMMON} ${${PROJECT_NAME}_LDFLAGS} ${DOTNET_LAUNCHER_UTIL}) + SET(NITOOL "nitool") SET(${NITOOL}_SOURCE_FILES - util/utils.cc - installer-plugin/common.cc installer-plugin/nitool.cc ) ADD_EXECUTABLE(${NITOOL} ${${NITOOL}_SOURCE_FILES}) SET_TARGET_PROPERTIES(${NITOOL} PROPERTIES COMPILE_FLAGS "-fPIE") -TARGET_LINK_LIBRARIES(${NITOOL} ${${PROJECT_NAME}_LDFLAGS} "-pie") +TARGET_LINK_LIBRARIES(${NITOOL} ${${PROJECT_NAME}_LDFLAGS} "-pie" ${DOTNET_LAUNCHER_UTIL} ${NI_COMMON}) #SET(INSTALLER_PLUGIN "ui-application") #SET(${INSTALLER_PLUGIN}_SOURCE_FILES @@ -111,21 +117,25 @@ TARGET_LINK_LIBRARIES(${NITOOL} ${${PROJECT_NAME}_LDFLAGS} "-pie") SET(PREFER_DOTNET_AOT_PLUGIN "prefer_dotnet_aot_plugin") SET(${PREFER_DOTNET_AOT_PLUGIN}_SOURCE_FILES - util/utils.cc - installer-plugin/common.cc installer-plugin/prefer_dotnet_aot_plugin.cc ) ADD_LIBRARY(${PREFER_DOTNET_AOT_PLUGIN} SHARED ${${PREFER_DOTNET_AOT_PLUGIN}_SOURCE_FILES}) SET_TARGET_PROPERTIES(${PREFER_DOTNET_AOT_PLUGIN} PROPERTIES COMPILE_FLAGS "-fPIC") -TARGET_LINK_LIBRARIES(${PREFER_DOTNET_AOT_PLUGIN} ${${PROJECT_NAME}_LDFLAGS}) - - -IF(NOT DEFINED NO_TIZEN) - INSTALL(TARGETS ${DOTNET_LAUNCHER} DESTINATION ${BINDIR}) - INSTALL(TARGETS ${NITOOL} DESTINATION ${BINDIR}) -# INSTALL(TARGETS ${INSTALLER_PLUGIN} DESTINATION ${INSTALL_PLUGIN_DIR}) - INSTALL(TARGETS ${PREFER_DOTNET_AOT_PLUGIN} DESTINATION ${INSTALL_MDPLUGIN_DIR}) - INSTALL(FILES dotnet.loader DESTINATION ${LOADERDIR}) - INSTALL(FILES dotnet.launcher DESTINATION ${LOADERDIR}) - INSTALL(FILES dotnet.debugger DESTINATION ${LOADERDIR}) -ENDIF(NOT DEFINED NO_TIZEN) +TARGET_LINK_LIBRARIES(${PREFER_DOTNET_AOT_PLUGIN} ${${PROJECT_NAME}_LDFLAGS} ${DOTNET_LAUNCHER_UTIL} ${NI_COMMON}) + +CONFIGURE_FILE(dotnet-launcher.pc.in dotnet-launcher.pc @ONLY) + +INSTALL(TARGETS ${DOTNET_LAUNCHER_UTIL} DESTINATION ${LIBDIR}) +INSTALL(TARGETS ${DOTNET_LAUNCHER} DESTINATION ${BINDIR}) +INSTALL(TARGETS ${NI_COMMON} DESTINATION ${LIBDIR}) +INSTALL(TARGETS ${NITOOL} DESTINATION ${BINDIR}) +#INSTALL(TARGETS ${INSTALLER_PLUGIN} DESTINATION ${INSTALL_PLUGIN_DIR}) +INSTALL(TARGETS ${PREFER_DOTNET_AOT_PLUGIN} DESTINATION ${INSTALL_MDPLUGIN_DIR}) +INSTALL(FILES dotnet.loader DESTINATION ${LOADERDIR}) +INSTALL(FILES dotnet.launcher DESTINATION ${LOADERDIR}) +INSTALL(FILES dotnet.debugger DESTINATION ${LOADERDIR}) +INSTALL(FILES inc/coreclr_host.h DESTINATION ${INCLUDEDIR}) +INSTALL(FILES inc/dotnet_launcher_plugin.h DESTINATION ${INCLUDEDIR}) +INSTALL(FILES installer-plugin/ni_common.h DESTINATION ${INCLUDEDIR}) +INSTALL(FILES ../dotnet-launcher.pc DESTINATION ${LIBDIR}/pkgconfig) + diff --git a/NativeLauncher/dotnet-launcher.pc.in b/NativeLauncher/dotnet-launcher.pc.in new file mode 100644 index 0000000..cf3257d --- /dev/null +++ b/NativeLauncher/dotnet-launcher.pc.in @@ -0,0 +1,9 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@ + +Name: dotnet-launcher +Description: Launchpad plugin for launching dotnet app and tools to generate ni files +Version: @Version@ +Libs: -L${libdir} -ldotnet_launcher_util -lni_common +Cflags: -I${includedir} diff --git a/NativeLauncher/inc/coreclr_host.h b/NativeLauncher/inc/coreclr_host.h new file mode 100644 index 0000000..7dbd137 --- /dev/null +++ b/NativeLauncher/inc/coreclr_host.h @@ -0,0 +1,52 @@ +/* + * 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 __CORECLR_HOST_H__ +#define __CORECLR_HOST_H__ + +extern "C" +{ + typedef int (*coreclr_initialize_ptr)( + const char* exePath, + const char* appDomainFriendlyName, + int propertyCount, + const char** propertyKeys, + const char** propertyValues, + void** hostHandle, + unsigned int* domainId); + + typedef int (*coreclr_execute_assembly_ptr)( + void* hostHandle, + unsigned int domainId, + int argc, + const char** argv, + const char* managedAssemblyPath, + unsigned int* exitCode); + + typedef int (*coreclr_shutdown_ptr)( + void* hostHandle, + unsigned int domainId); + + typedef int (*coreclr_create_delegate_ptr)( + void* hostHandle, + unsigned int domainId, + const char* entryPointAssemblyName, + const char* entryPointTypeName, + const char* entryPointMethodName, + void** delegate); +} + +#endif /* __CORECLR_HOST_H__ */ diff --git a/NativeLauncher/inc/dotnet_launcher_plugin.h b/NativeLauncher/inc/dotnet_launcher_plugin.h new file mode 100644 index 0000000..4e75917 --- /dev/null +++ b/NativeLauncher/inc/dotnet_launcher_plugin.h @@ -0,0 +1,38 @@ +/* + * 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_PLUGIN_H__ +#define __DOTNET_LAUNCHER_PLUGIN_H__ + +#include "coreclr_host.h" + +extern "C" +{ + typedef void (*plugin_initialize_ptr)(const char* mode); + typedef void (*plugin_preload_ptr)(); + typedef void (*plugin_set_app_info_ptr)( + const char* appId, + const char* managedAssemblyPath); + typedef void (*plugin_set_coreclr_info_ptr)( + void* hostHandle, + unsigned int domainId, + coreclr_create_delegate_ptr delegateFunc); + typedef char* (*plugin_get_dll_path_ptr)(); + typedef void (*plugin_before_execute_ptr)(); + typedef void (*plugin_finalize_ptr)(); +} + +#endif /* __DOTNET_LAUNCHER_PLUGIN_H__ */ diff --git a/NativeLauncher/inc/plugin_manager.h b/NativeLauncher/inc/plugin_manager.h new file mode 100644 index 0000000..94e1798 --- /dev/null +++ b/NativeLauncher/inc/plugin_manager.h @@ -0,0 +1,50 @@ +/* + * 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 __PLUGIN_MANAGER_H__ +#define __PLUGIN_MANAGER_H__ + +#include "dotnet_launcher_plugin.h" +#include "coreclr_host.h" + +extern "C" +{ + + +typedef struct PluginFunc { + plugin_initialize_ptr initialize; + plugin_preload_ptr preload; + plugin_set_app_info_ptr set_app_info; + plugin_set_coreclr_info_ptr set_coreclr_info; + plugin_get_dll_path_ptr get_dll_path; + plugin_before_execute_ptr before_execute; + plugin_finalize_ptr finalize; +} PluginFunc; + +// plugin functions +void pluginPreload(); +void pluginSetAppInfo(const char* appId, const char* managedAssemblyPath); +void pluginSetCoreclrInfo(void* hostHandle, unsigned int domainId, coreclr_create_delegate_ptr delegateFunc); +char* pluginGetDllPath(); +void pluginBeforeExecute(); + +// initialize / finalize plugin manager +int initializePluginManager(const char* mode); +void finalizePluginManager(); + +} + +#endif /* __PLUGIN_MANAGER_H__ */ diff --git a/NativeLauncher/inc/utils.h b/NativeLauncher/inc/utils.h index 18fdaa0..534be8b 100644 --- a/NativeLauncher/inc/utils.h +++ b/NativeLauncher/inc/utils.h @@ -26,24 +26,23 @@ #define PATH_SEPARATOR '/' #endif -bool iCompare(const std::string& a, const std::string& b); -bool iCompare(const std::string& a, int aOffset, const std::string& b, int bOffset, int length); -bool isManagedAssembly(const std::string& fileName); -bool isNativeImage(const std::string& fileName); std::string readSelfPath(); + std::string concatPath(const std::string& path1, const std::string& path2); -void splitPath(const std::string& path, std::vector& out); -void appendPath(std::string& path1, const std::string& path2); std::string absolutePath(const std::string& path); std::string baseName(const std::string& path); -bool endWithIgnoreCase(const std::string& str1, const std::string& str2, std::string& fileName); -void assembliesInDirectory(const std::vector& directories, std::string& tpaList); +void splitPath(const std::string& path, std::vector& out); +void appendPath(std::string& path1, const std::string& path2); + +bool isFileExist(const std::string& path); + +bool isManagedAssembly(const std::string& fileName); +bool isNativeImage(const std::string& fileName); -bool fileNotExist(const std::string& path); -std::string joinStrings(const std::vector& strings, const char* const delimeter); +void assembliesInDirectory(const std::vector& directories, std::string& tpaList); -typedef std::function FileReader; -void scanFilesInDir(const char* directory, FileReader reader, unsigned int depth); +typedef std::function FileReader; +void scanFilesInDir(const std::string& directory, FileReader reader, unsigned int depth); int runLoggingThread(); #endif /* __UTILS_H__ */ diff --git a/NativeLauncher/installer-plugin/common.cc b/NativeLauncher/installer-plugin/common.cc deleted file mode 100644 index 31596f4..0000000 --- a/NativeLauncher/installer-plugin/common.cc +++ /dev/null @@ -1,500 +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 -#include -#include - -#include "log.h" -#include "utils.h" -#include "pkgmgr_parser_plugin_interface.h" - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "common.h" - -#ifdef LOG_TAG -#undef LOG_TAG -#endif -#define LOG_TAG "NETCORE_INSTALLER_PLUGIN" - -#ifndef DEVICE_API_DIR -#error "DEVICE_API_DIR is missed" -#endif - -#ifndef RUNTIME_DIR -#error "RUNTIME_DIR is missed" -#endif - -#ifndef CROSSGEN_PATH -#error "CROSSGEN_PATH is missed" -#endif - -#define __XSTR(x) #x -#define __STR(x) __XSTR(x) -static const char* __DEVICE_API_DIR = __STR(DEVICE_API_DIR); -static const char* __RUNTIME_DIR = __STR(RUNTIME_DIR); -static const char* __CROSSGEN_PATH = __STR(CROSSGEN_PATH); -static const char* __JIT_PATH = __STR(RUNTIME_DIR)"/libclrjit.so"; -#undef __STR -#undef __XSTR - -#if 0 -static std::string replace(std::string &str, const std::string& from, const std::string& to) -{ - size_t startPos = 0; - while ((startPos = str.find(from, startPos)) != std::string::npos) { - str.replace(startPos, from.length(), to); - startPos += to.length(); - } - return str; -} -#endif - -static void smack_(const char* dllPath, const char* label) -{ - static const char* chsmack = "/usr/bin/chsmack"; - pid_t pid = fork(); - if (pid == -1) - return; - - if (pid > 0) { - int status; - waitpid(pid, &status, 0); - if (WIFEXITED(status)) - return; - } else { - const char* args[] = { - chsmack, - "-a", label, - dllPath, - nullptr - }; - execv(chsmack, const_cast(args)); - - exit(0); - } -} - -static void crossgen(const char* dllPath, const char* appPath, bool enableR2R) -{ - //pid_t parent = getpid(); - pid_t pid = fork(); - if (pid == -1) - return; - - if (pid > 0) { - int status; - waitpid(pid, &status, 0); - if (WIFEXITED(status)) - return; - } else { - // search dlls in the application directory first, to use application dlls - // instead of system dlls when proceeding NI - std::vector tpaDir; - if (appPath != NULL) { - std::string path(appPath); - std::string::size_type prevPos = 0, pos = 0; - while ((pos = path.find(':', pos)) != std::string::npos) { - std::string substring(path.substr(prevPos, pos - prevPos)); - tpaDir.push_back(substring); - prevPos = ++pos; - } - std::string substring(path.substr(prevPos, pos - prevPos)); - tpaDir.push_back(substring); - } - tpaDir.push_back(__RUNTIME_DIR); - tpaDir.push_back(__DEVICE_API_DIR); - - // get reference API directory ([DEVICE_API_DIR]/ref) - int len = strlen(__DEVICE_API_DIR); - char* refAPIDir = (char*)calloc(len + 5, 1); - if (!refAPIDir) { - printf("fail to allocate memory for reference API directory\n"); - return; - } - snprintf(refAPIDir, len + 5, "%s%s", __DEVICE_API_DIR, "/ref"); - tpaDir.push_back(refAPIDir); - - std::string tpa; - assembliesInDirectory(tpaDir, tpa); - - std::vector argv = { - __CROSSGEN_PATH, - "/Trusted_Platform_Assemblies", tpa.c_str(), - "/JITPath", __JIT_PATH - }; - - if (!enableR2R) { - fprintf(stderr, "FNV mode enabled!!!\n"); - argv.push_back("/FragileNonVersionable"); - } else { - fprintf(stderr, "R2R mode enabled!!!\n"); - } - - if (appPath != nullptr) { - argv.push_back("/App_Paths"); - argv.push_back(appPath); - } - argv.push_back(dllPath); - argv.push_back(nullptr); - - printf("+ %s\n", dllPath); - - execv(__CROSSGEN_PATH, const_cast(argv.data())); - exit(0); - } -} - -static int getRootPath(const char *pkgId, std::string& rootPath) -{ - int ret = 0; - char *path = 0; - - uid_t uid = 0; - - if (pkgmgr_installer_info_get_target_uid(&uid) < 0) { - _ERR("Failed to get UID"); - return -1; - } - - _INFO("user id is %d", uid); - - pkgmgrinfo_pkginfo_h handle; - if (uid == 0) { - ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId, &handle); - if (ret != PMINFO_R_OK) - return -1; - } else { - ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId, uid, &handle); - if (ret != PMINFO_R_OK) - return -1; - } - - ret = pkgmgrinfo_pkginfo_get_root_path(handle, &path); - if (ret != PMINFO_R_OK) { - pkgmgrinfo_pkginfo_destroy_pkginfo(handle); - return -1; - } - rootPath = path; - pkgmgrinfo_pkginfo_destroy_pkginfo(handle); - - return 0; -} - -static bool niExist(const std::string& path, std::string& ni) -{ - // native image of System.Private.CoreLib.dll should have to overwrite - // original file to support new coreclr - if (path.find("System.Private.CoreLib.dll") != std::string::npos) { - std::string coreLibBackup = path + ".Backup"; - if (!fileNotExist(coreLibBackup)) { - ni = path; - return true; - } - return false; - } - - static const char* possibleExts[] = { - ".ni.dll", ".NI.dll", ".NI.DLL", ".ni.DLL", - ".ni.exe", ".NI.exe", ".NI.EXE", ".ni.EXE" - }; - std::string fName = path.substr(0, path.size() - 4); - - struct stat sb; - - for (const char* ext : possibleExts) { - std::string f = fName + ext; - if (stat(f.c_str(), &sb) == 0) { - ni = f; - return true; - } - } - - return false; -} - -static int appAotCb(pkgmgrinfo_appinfo_h handle, void *userData) -{ - char *pkgId = NULL; - int ret = 0; - - ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId); - if (ret != PMINFO_R_OK) { - _DBG("Failed to get pkgid"); - return -1; - } - - // When you create native image with pkgid, ni file is generated even though already ni file exist. - // Regenerate ni files with R2R mode forcibiliy. (there is no way to now which option is used) - if (createNiUnderPkgRoot(pkgId, true) != 0) { - _ERR("Failed to get root path from [%s]", pkgId); - return -1; - } else { - _DBG("Complete make application to native image"); - } - - return 0; -} - -int regenerateAppNI() -{ - int ret = 0; - pkgmgrinfo_appinfo_metadata_filter_h handle; - - ret = pkgmgrinfo_appinfo_metadata_filter_create(&handle); - if (ret != PMINFO_R_OK) - return -1; - - ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, "http://tizen.org/metadata/prefer_dotnet_aot", "true"); - if (ret != PMINFO_R_OK) { - pkgmgrinfo_appinfo_metadata_filter_destroy(handle); - return -1; - } - - ret = pkgmgrinfo_appinfo_metadata_filter_foreach(handle, appAotCb, NULL); - if (ret != PMINFO_R_OK) { - _DBG("Failed pkgmgrinfo_appinfo_metadata_filter_foreach"); - pkgmgrinfo_appinfo_metadata_filter_destroy(handle); - return -1; - } - - _DBG("Success pkgmgrinfo_appinfo_metadata_filter_foreach"); - - pkgmgrinfo_appinfo_metadata_filter_destroy(handle); - return 0; -} - -static void createCoreLibNI(bool enableR2R) -{ - std::string coreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll"); - std::string niCoreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.ni.dll"); - std::string coreLibBackup = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll.Backup"); - - if (!niExist(coreLib, niCoreLib)) { - crossgen(coreLib.c_str(), nullptr, enableR2R); - if (!fileNotExist(niCoreLib)) { - // change owner and groups for generated ni file. - struct stat info; - if (!stat(coreLib.c_str(), &info)) { - if (chown(niCoreLib.c_str(), info.st_uid, info.st_gid) == -1) - _ERR("Failed to change owner and group name"); - } - smack_(niCoreLib.c_str(), "_"); - rename(coreLib.c_str(), coreLibBackup.c_str()); - rename(niCoreLib.c_str(), coreLib.c_str()); - } - } -} - -void removeNiUnderDirs(const char* rootPaths[], int count) -{ - auto convert = [](const char* path, const char* name) { - std::string ni; - if (isNativeImage(path)) { - remove(path); - } - }; - - for (int i = 0; i < count; i++) - scanFilesInDir(rootPaths[i], convert, -1); -} - -void removeNiPlatform() -{ - std::string coreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll"); - std::string coreLibBackup = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll.Backup"); - - if (fileNotExist(coreLibBackup)) { - return; - } - - if (remove(coreLib.c_str())) { - _ERR("Failed to remove System.Private.CoreLib native image file"); - } - - rename(coreLibBackup.c_str(), coreLib.c_str()); - - const char* platformDirs[] = {__RUNTIME_DIR, __DEVICE_API_DIR, "/usr/bin"}; - - removeNiUnderDirs(platformDirs, 3); -} - -void createNiPlatform(bool enableR2R) -{ - createCoreLibNI(enableR2R); - - const char* platformDirs[] = {__RUNTIME_DIR, __DEVICE_API_DIR, "/usr/bin"}; - - createNiUnderDirs(platformDirs, 3, [](const char* ni) { - smack_(ni, "_"); - }, enableR2R); -} - -void createNiSelect(const char* dllPath, bool enableR2R) -{ - createCoreLibNI(enableR2R); - - std::string niPath; - if (!fileNotExist(dllPath)) { - if (!niExist(dllPath, niPath)) { - crossgen(dllPath, nullptr, enableR2R); - if (niExist(dllPath, niPath)) { - // change owner and groups for generated ni file. - struct stat info; - if (!stat(dllPath, &info)) { - if (chown(niPath.c_str(), info.st_uid, info.st_gid) == -1) - _ERR("Failed to change owner and group name"); - } - smack_(niPath.c_str(), "_"); - } - } else { - printf("Already [%s] file is exist\n", niPath.c_str()); - } - } else { - printf("Failed to find dll : %s", dllPath); - } -} - -void createNiUnderDirs(const char* rootPaths[], int count, const char* ignores[], int igcount, afterCreate cb, bool update, bool enableR2R) -{ - std::string appPaths; - for (int i = 0; i < count; i++) { - appPaths += rootPaths[i]; - appPaths += ':'; - } - - if (appPaths.back() == ':') - appPaths.pop_back(); - - auto convert = [&appPaths, ignores, igcount, &cb, update, enableR2R](const char* path, const char* name) { - for (int i = 0; i < igcount; i++) { - if (strcmp(path, ignores[i]) == 0) - return; - } - std::string niPath; - if (isManagedAssembly(path) && !isNativeImage(path)) { - if (niExist(path, niPath)) { - if (update && !niPath.empty()) { - _INFO("override [%s] file", niPath.c_str()); - } else { - _INFO("Already [%s] file is exist", niPath.c_str()); - return; - } - } - crossgen(path, appPaths.c_str(), enableR2R); - if (niExist(path, niPath)) { - // change owner and groups for generated ni file. - struct stat info; - if (!stat(path, &info)) { - if (chown(niPath.c_str(), info.st_uid, info.st_gid) == -1) - _ERR("Failed to change owner and group name"); - } - - if (cb != nullptr) - cb(niPath.c_str()); - } else { - _INFO("Failed to create native image for %s", path); - } - } - }; - - for (int i = 0; i < count; i++) - scanFilesInDir(rootPaths[i], convert, 1); -} -void createNiUnderDirs(const char* rootPaths[], int count, afterCreate cb, bool update, bool enableR2R) -{ - createNiUnderDirs(rootPaths, count, nullptr, 0, cb, update, enableR2R); -} -void createNiUnderDirs(const char* rootPaths[], int count, bool update, bool enableR2R) -{ - createNiUnderDirs(rootPaths, count, nullptr, update, enableR2R); -} - -int removeNiUnderPkgRoot(const char* pkgName) -{ - std::string pkgRoot; - if (getRootPath(pkgName, pkgRoot) < 0) - return 1; - - std::string binDir = concatPath(pkgRoot, "bin"); - std::string libDir = concatPath(pkgRoot, "lib"); - _INFO("bindir : %s", binDir.c_str()); - _INFO("libdir : %s", libDir.c_str()); - - const char* paths[] = { - binDir.c_str(), - libDir.c_str() - }; - - removeNiUnderDirs(paths, 2); - - return 0; -} - - -int createNiUnderPkgRoot(const char* pkgName, bool enableR2R) -{ - std::string pkgRoot; - if (getRootPath(pkgName, pkgRoot) < 0) - return 1; - - // get interval value - const char* intervalFile = "/usr/share/dotnet.tizen/lib/crossgen_interval.txt"; - int interval = 0; - std::ifstream inFile(intervalFile); - if (inFile) { - _INFO("crossgen_interval.txt is found"); - inFile >> interval; - } else { - _INFO("fail to read crossgen_interval.txt file"); - } - - std::string binDir = concatPath(pkgRoot, "bin"); - std::string libDir = concatPath(pkgRoot, "lib"); - _INFO("bindir : %s", binDir.c_str()); - _INFO("libdir : %s", libDir.c_str()); - - const char* paths[] = { - binDir.c_str(), - libDir.c_str() - }; - - // change smack label for generated ni file. - std::string label = "User::Pkg::" + std::string(pkgName) + "::RO"; - createNiUnderDirs(paths, 2, [label, interval](const char* ni) { - smack_(ni, label.c_str()); - if (interval != 0) { - _INFO("sleep %d usec", interval); - usleep(interval); - } - }, true, enableR2R); - - return 0; -} diff --git a/NativeLauncher/installer-plugin/common.h b/NativeLauncher/installer-plugin/common.h deleted file mode 100644 index 325bb82..0000000 --- a/NativeLauncher/installer-plugin/common.h +++ /dev/null @@ -1,33 +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 __INSTALLER_PLUGIN_COMMON_H__ -#define __INSTALLER_PLUGIN_COMMON_H__ - -#include - -typedef std::function afterCreate; -int regenerateAppNI(); -void createNiUnderDirs(const char* rootPaths[], int count, const char* ignores[], int igcount, afterCreate cb, bool update, bool enableR2R); -void createNiUnderDirs(const char* rootPaths[], int count, afterCreate cb, bool update, bool enableR2R); -void createNiUnderDirs(const char* rootPaths[], int count, bool update, bool enableR2R); -int createNiUnderPkgRoot(const char* pkgName, bool enableR2R); -void createNiPlatform(bool enableR2R); -void createNiSelect(const char* dllPath, bool enableR2R); -void removeNiPlatform(); -int removeNiUnderPkgRoot(const char* pkgName); - -#endif /* __INSTALLER_PLUGIN_COMMON_H__ */ diff --git a/NativeLauncher/installer-plugin/ni_common.cc b/NativeLauncher/installer-plugin/ni_common.cc new file mode 100644 index 0000000..7bdaa2f --- /dev/null +++ b/NativeLauncher/installer-plugin/ni_common.cc @@ -0,0 +1,486 @@ +/* + * 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 +#include +#include + +#include "log.h" +#include "utils.h" +#include "pkgmgr_parser_plugin_interface.h" + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "ni_common.h" +#include "path_manager.h" +#include "plugin_manager.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "NETCORE_INSTALLER_PLUGIN" + +#ifndef CROSSGEN_PATH +#error "CROSSGEN_PATH is missed" +#endif + +#define __XSTR(x) #x +#define __STR(x) __XSTR(x) +static const char* __CROSSGEN_PATH = __STR(CROSSGEN_PATH); +#undef __STR +#undef __XSTR + +static int __interval = 0; + +static void waitInterval() +{ + if (__interval > 0) { + fprintf(stderr, "sleep %d usec\n", __interval); + usleep(__interval); + } +} + +static bool niExist(const std::string& path, std::string& ni) +{ + static std::string possibleExts[] = { + ".ni.dll", ".NI.dll", ".NI.DLL", ".ni.DLL", + ".ni.exe", ".NI.exe", ".NI.EXE", ".ni.EXE" + }; + std::string fName = path.substr(0, path.size() - 4); + + struct stat sb; + + for (std::string ext : possibleExts) { + std::string f = fName + ext; + if (stat(f.c_str(), &sb) == 0) { + ni = f; + return true; + } + } + + // native image of System.Private.CoreLib.dll should have to overwrite + // original file to support new coreclr + if (path.find("System.Private.CoreLib.dll") != std::string::npos) { + std::string coreLibBackup = path + ".Backup"; + if (isFileExist(coreLibBackup)) { + ni = path; + return true; + } + } + + return false; +} + +static void updateNiFileInfo(const std::string& path) +{ + char* label = NULL; + std::string niPath; + + if (niExist(path, niPath)) { + // change smack label + if (smack_getlabel(path.c_str(), &label, SMACK_LABEL_ACCESS) == 0) { + if (smack_setlabel(niPath.c_str(), label, SMACK_LABEL_ACCESS) < 0) { + fprintf(stderr, "Fail to set smack label\n"); + } + free(label); + } + + // change owner and groups for generated ni file. + struct stat info; + if (!stat(path.c_str(), &info)) { + if (chown(niPath.c_str(), info.st_uid, info.st_gid) == -1) + fprintf(stderr, "Failed to change owner and group name\n"); + } + } +} + +static void crossgen(const std::string& dllPath, const std::string& appPath, bool enableR2R) +{ + std::string absDllPath = absolutePath(dllPath); + + pid_t pid = fork(); + if (pid == -1) + return; + + if (pid > 0) { + int status; + waitpid(pid, &status, 0); + if (WIFEXITED(status)) { + updateNiFileInfo(absDllPath); + return; + } + } else { + std::string tpa = getTPA(); + std::string jitPath = getRuntimeDir() + "/libclrjit.so"; + std::vector argv = { + __CROSSGEN_PATH, + "/nologo", + "/Trusted_Platform_Assemblies", tpa.c_str(), + "/JITPath", jitPath.c_str() + }; + + if (!enableR2R) { + argv.push_back("/FragileNonVersionable"); + } + + argv.push_back("/App_Paths"); + std::string absAppPath; + if (!appPath.empty()) { + absAppPath = appPath; + } else { + absAppPath = baseName(absDllPath); + } + argv.push_back(absAppPath.c_str()); + + argv.push_back(absDllPath.c_str()); + argv.push_back(nullptr); + + fprintf(stderr, "+ %s (%s)\n", absDllPath.c_str(), enableR2R ? "R2R" : "FNV"); + + execv(__CROSSGEN_PATH, const_cast(argv.data())); + exit(0); + } +} + +static int getRootPath(std::string pkgId, std::string& rootPath) +{ + int ret = 0; + char *path = 0; + + uid_t uid = 0; + + if (pkgmgr_installer_info_get_target_uid(&uid) < 0) { + _ERR("Failed to get UID"); + return -1; + } + + pkgmgrinfo_pkginfo_h handle; + if (uid == 0) { + ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId.c_str(), &handle); + if (ret != PMINFO_R_OK) + return -1; + } else { + ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId.c_str(), uid, &handle); + if (ret != PMINFO_R_OK) + return -1; + } + + ret = pkgmgrinfo_pkginfo_get_root_path(handle, &path); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + return -1; + } + rootPath = path; + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + + return 0; +} + + +static int appAotCb(pkgmgrinfo_appinfo_h handle, void *userData) +{ + char *pkgId = NULL; + int ret = 0; + + ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId); + if (ret != PMINFO_R_OK) { + fprintf(stderr, "Failed to get pkgid\n"); + return -1; + } + + if (removeNiUnderPkgRoot(pkgId) != 0) { + fprintf(stderr, "Failed to remove previous dlls from [%s]\n", pkgId); + return -1; + } + + // Regenerate ni files with R2R mode forcibiliy. (there is no way to now which option is used) + if (createNiUnderPkgRoot(pkgId, true) != 0) { + fprintf(stderr, "Failed to get root path from [%s]\n", pkgId); + return -1; + } else { + fprintf(stderr, "Complete make application to native image\n"); + } + + return 0; +} + +static void createCoreLibNI(bool enableR2R) +{ + std::string coreLib = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll"); + std::string niCoreLib = concatPath(getRuntimeDir(), "System.Private.CoreLib.ni.dll"); + std::string coreLibBackup = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll.Backup"); + + if (!niExist(coreLib, niCoreLib)) { + crossgen(coreLib, std::string(), enableR2R); + if (isFileExist(niCoreLib)) { + if (rename(coreLib.c_str(), coreLibBackup.c_str())) { + fprintf(stderr, "Failed to rename System.Private.CoreLib.dll\n"); + } + if (rename(niCoreLib.c_str(), coreLib.c_str())) { + fprintf(stderr, "Failed to rename System.Private.CoreLib.ni.dll\n"); + } + } else { + fprintf(stderr, "Failed to create native image for %s\n", coreLib.c_str()); + } + } +} + +int initNICommon(NiCommonOption* option) +{ + // get interval value + const char* intervalFile = "/usr/share/dotnet.tizen/lib/crossgen_interval.txt"; + std::ifstream inFile(intervalFile); + if (inFile) { + fprintf(stderr, "crossgen_interval.txt is found\n"); + inFile >> __interval; + } + + if (initializePluginManager("normal")) { + fprintf(stderr, "Fail to initialize plugin manager\n"); + return -1; + } + if (initializePathManager(option->runtimeDir, option->tizenFXDir, option->extraDirs)) { + fprintf(stderr, "Fail to initialize path manager\n"); + return -1; + } + + return 0; +} + +void finalizeNICommon() +{ + __interval = 0; + + finalizePluginManager(); + finalizePathManager(); +} + + +void createNiPlatform(bool enableR2R) +{ + const std::string platformDirs[] = {getRuntimeDir(), getTizenFXDir()}; + + createNiUnderDirs(platformDirs, 2, enableR2R); +} + +void createNiDll(const std::string& dllPath, bool enableR2R) +{ + createCoreLibNI(enableR2R); + + if (!isFileExist(dllPath)) { + fprintf(stderr, "Failed to find dll : %s\n", dllPath.c_str()); + return; + } + + std::string niPath; + if (niExist(dllPath, niPath)) { + fprintf(stderr, "Already [%s] file is exist\n", niPath.c_str()); + return; + } + + crossgen(dllPath, std::string(), enableR2R); + if (!niExist(dllPath, niPath)) { + fprintf(stderr, "Failed to create native image for %s\n", dllPath.c_str()); + } +} + +void createNiUnderDirs(const std::string rootPaths[], int count, const std::string ignores[], int igcount, afterCreate cb, bool enableR2R) +{ + createCoreLibNI(enableR2R); + + std::string appPaths; + for (int i = 0; i < count; i++) { + appPaths += rootPaths[i]; + appPaths += ':'; + } + + if (appPaths.back() == ':') + appPaths.pop_back(); + + auto convert = [&appPaths, ignores, igcount, &cb, enableR2R](const std::string& path, const char* name) { + for (int i = 0; i < igcount; i++) { + if (path == ignores[i]) + return; + } + std::string niPath; + if (isManagedAssembly(path)) { + if (niExist(path, niPath)) { + fprintf(stderr, "Already [%s] file is exist\n", niPath.c_str()); + return; + } + fprintf(stderr, "path [%s], appPath[%s]\n", path.c_str(), appPaths.c_str()); + crossgen(path, appPaths.c_str(), enableR2R); + if (niExist(path, niPath)) { + if (cb != nullptr) + cb(niPath.c_str()); + } else { + fprintf(stderr, "Failed to create native image for %s\n", path.c_str()); + } + waitInterval(); + } + }; + + for (int i = 0; i < count; i++) + scanFilesInDir(rootPaths[i], convert, 1); +} +void createNiUnderDirs(const std::string rootPaths[], int count, afterCreate cb, bool enableR2R) +{ + createNiUnderDirs(rootPaths, count, nullptr, 0, cb, enableR2R); +} +void createNiUnderDirs(const std::string rootPaths[], int count, bool enableR2R) +{ + createNiUnderDirs(rootPaths, count, nullptr, enableR2R); +} + +int createNiUnderPkgRoot(const std::string& pkgName, bool enableR2R) +{ + std::string pkgRoot; + if (getRootPath(pkgName, pkgRoot) < 0) + return -1; + + std::string binDir = concatPath(pkgRoot, "bin"); + std::string libDir = concatPath(pkgRoot, "lib"); + std::string paths[] = {binDir, libDir}; + + createNiUnderDirs(paths, 2, enableR2R); + + return 0; +} + +int createNiDllUnderPkgRoot(const std::string& pkgName, const std::string& dllPath, bool enableR2R) +{ + std::string pkgRoot; + if (getRootPath(pkgName, pkgRoot) < 0) + return -1; + + std::string binDir = concatPath(pkgRoot, "bin"); + std::string libDir = concatPath(pkgRoot, "lib"); + std::string appPaths = binDir + ":" + libDir; + + if (!isFileExist(dllPath)) { + fprintf(stderr, "Failed to find dll : %s\n", dllPath.c_str()); + return -1; + } + + std::string niPath; + if (niExist(dllPath, niPath)) { + fprintf(stderr, "Already [%s] file is exist\n", niPath.c_str()); + return -1; + } + + crossgen(dllPath, appPaths, enableR2R); + if (!niExist(dllPath, niPath)) { + fprintf(stderr, "Failed to create native image for %s\n", dllPath.c_str()); + return -1; + } + + return 0; +} + +void removeNiPlatform() +{ + std::string coreLib = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll"); + std::string coreLibBackup = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll.Backup"); + + if (!isFileExist(coreLibBackup)) { + return; + } + + if (remove(coreLib.c_str())) { + fprintf(stderr, "Failed to remove System.Private.CoreLib native image file\n"); + } + + if (rename(coreLibBackup.c_str(), coreLib.c_str())) { + fprintf(stderr, "Failed to rename System.Private.CoreLib.Backup to origin\n"); + } + + const std::string platformDirs[] = {getRuntimeDir(), getTizenFXDir()}; + + removeNiUnderDirs(platformDirs, 2); +} + +void removeNiUnderDirs(const std::string rootPaths[], int count) +{ + auto convert = [](const std::string& path, std::string name) { + std::string ni; + if (isNativeImage(path)) { + if (remove(path.c_str())) { + fprintf(stderr, "Failed to remove %s\n", path.c_str()); + } + } + }; + + for (int i = 0; i < count; i++) + scanFilesInDir(rootPaths[i], convert, -1); +} + +int removeNiUnderPkgRoot(const std::string& pkgName) +{ + std::string pkgRoot; + if (getRootPath(pkgName, pkgRoot) < 0) + return -1; + + std::string binDir = concatPath(pkgRoot, "bin"); + std::string libDir = concatPath(pkgRoot, "lib"); + std::string paths[] = {binDir, libDir}; + + removeNiUnderDirs(paths, 2); + + return 0; +} + +int regenerateAppNI() +{ + int ret = 0; + pkgmgrinfo_appinfo_metadata_filter_h handle; + + ret = pkgmgrinfo_appinfo_metadata_filter_create(&handle); + if (ret != PMINFO_R_OK) + return -1; + + ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, "http://tizen.org/metadata/prefer_dotnet_aot", "true"); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_appinfo_metadata_filter_destroy(handle); + return -1; + } + + ret = pkgmgrinfo_appinfo_metadata_filter_foreach(handle, appAotCb, NULL); + if (ret != PMINFO_R_OK) { + fprintf(stderr, "Failed pkgmgrinfo_appinfo_metadata_filter_foreach\n"); + pkgmgrinfo_appinfo_metadata_filter_destroy(handle); + return -1; + } + + fprintf(stderr, "Success pkgmgrinfo_appinfo_metadata_filter_foreach\n"); + + pkgmgrinfo_appinfo_metadata_filter_destroy(handle); + return 0; +} + diff --git a/NativeLauncher/installer-plugin/ni_common.h b/NativeLauncher/installer-plugin/ni_common.h new file mode 100644 index 0000000..d142f7d --- /dev/null +++ b/NativeLauncher/installer-plugin/ni_common.h @@ -0,0 +1,127 @@ +/* + * 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 __NI_COMMON_H__ +#define __NI_COMMON_H__ + +#include + +typedef std::function afterCreate; + +/** + * @brief : structure which contains directory info + */ +typedef struct NiCommonOption { + std::string runtimeDir; /**< .NETCore Runtime directory */ + std::string tizenFXDir; /**< TizenFX directory */ + std::string extraDirs; /**< ":" seperated directories which can be set by plugins */ +} NiCommonOption; + +/** + * @brief initialize NICommon + * @param[in] options to initialize path + * @return 0 on success, otherwise a negative error value + */ +int initNICommon(NiCommonOption* option); + +/** + * @brief finalize NICommon + * @details Before re-initialize NICommon, you have to finalize current NICommon first. + */ +void finalizeNICommon(); + +/** + * @brief create native images (NI file) for Platform DLLs (.NETCore + TizenFX) + */ +void createNiPlatform(bool enableR2R); + +/** + * @brief create native image for specific dll with file path. + * @param[i] dllPath file path to generate native image + * @param[i] enableR2R enable ready-to-run mode + */ +void createNiDll(const std::string& dllPath, bool enableR2R); + +/** + * @brief create native images with files under specific directory. + * @param[i] rootPaths directories whicn contains DLLs + * @param[i] count number of rootPath + * @param[i] ignores DLL list which should be ignored + * @param[i] igcount number of ignores + * @param[i] cb callback function whicn will be called after generating native image + * @param[i] enableR2R enable ready-to-run mode + */ +void createNiUnderDirs(const std::string rootPaths[], int count, const std::string ignores[], int igcount, afterCreate cb, bool enableR2R); + +/** + * @brief create native images with files under specific directory. + * @param[i] rootPaths directories whicn contains DLLs + * @param[i] count number of rootPath + * @param[i] cb callback function whicn will be called after generating native image + * @param[i] enableR2R enable ready-to-run mode + */ +void createNiUnderDirs(const std::string rootPaths[], int count, afterCreate cb, bool enableR2R); + +/** + * @brief create native images with files under specific directory. + * @param[i] rootPaths directories whicn contains DLLs + * @param[i] count number of rootPath + * @param[i] enableR2R enable ready-to-run mode + */ +void createNiUnderDirs(const std::string rootPaths[], int count, bool enableR2R); + +/** + * @brief create native images for specific package. (All DLLs) + * @param[i] pkgId package ID + * @param[i] enableR2R enable ready-to-run mode + * @return 0 on success, otherwise a negative error value + */ +int createNiUnderPkgRoot(const std::string& pkgId, bool enableR2R); + +/** + * @brief create native image for specific dll in the package. + * @Details All dlls in the package are added for reference when create native image. + * @param[i] pkgId package ID + * @param[i] enableR2R enable ready-to-run mode + * @return 0 on success, otherwise a negative error value + */ +int createNiDllUnderPkgRoot(const std::string& pkgId, const std::string& dllPath, bool enableR2R); + +/** + * @brief remove native images (NI file) for Platform DLLs (.NETCore + TizenFX) + */ +void removeNiPlatform(); + +/** + * @brief remove native images under specific directory. + * @param[i] rootPaths directories whicn contains native image + * @param[i] count number of rootPath + */ +void removeNiUnderDirs(const std::string rootPaths[], int count); + +/** + * @brief remove native images for specific package. + * @param[i] pkgId package ID + * @return 0 on success, otherwise a negative error value + */ +int removeNiUnderPkgRoot(const std::string& pkgId); + +/** + * @brief regenerate native image for all installed application + */ +int regenerateAppNI(); + +#endif /* __NI_COMMON_H__ */ diff --git a/NativeLauncher/installer-plugin/nitool.cc b/NativeLauncher/installer-plugin/nitool.cc index bb996af..5d7edcc 100644 --- a/NativeLauncher/installer-plugin/nitool.cc +++ b/NativeLauncher/installer-plugin/nitool.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "common.h" +#include "ni_common.h" #include #include @@ -22,9 +22,9 @@ #include #include -std::vector getCmdArgs(char** begin, char** end) +std::vector getCmdArgs(char** begin, char** end) { - std::vector list; + std::vector list; for (char** itr = begin+1; itr != end; itr++) { if (strncmp(*itr, "--", 2) != 0) list.push_back(*itr); @@ -68,6 +68,13 @@ int main(int argc, char* argv[]) bool dirMode = false; bool rmPkgMode = false; bool enableR2R = false; + bool pkgDllMode = false; + + NiCommonOption option = {std::string(), std::string(), std::string()}; + if (initNICommon(&option) < 0) { + fprintf(stderr, "Fail to initialize NI Common\n"); + return -1; + } if (cmdOptionExists(argv, argv+argc, "--r2r")) { enableR2R = true; @@ -93,12 +100,14 @@ int main(int argc, char* argv[]) } else if (cmdOptionExists(argv, argv+argc, "--regen-all-app")) { regenerateAppNI(); return 0; + } else if (cmdOptionExists(argv, argv+argc, "--pkg-dll")) { + pkgDllMode = true; } else { help(argv[0]); - return 1; + return 0; } - std::vector args = getCmdArgs(argv, argv+argc); + std::vector args = getCmdArgs(argv, argv+argc); if (args.size() < 1) { if (pkgMode) @@ -110,24 +119,29 @@ int main(int argc, char* argv[]) } if (pkgMode) { - for (const char* pkg : args) { + for (const std::string pkg : args) { if (createNiUnderPkgRoot(pkg, enableR2R) != 0) { - fprintf(stderr, "Failed to get root path from [%s]\n", pkg); - return 1; + fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str()); + return -1; } } + } if (pkgDllMode) { + if (createNiDllUnderPkgRoot(args[0], args[1], enableR2R) != 0) { + fprintf(stderr, "Failed to get root path from [%s]\n", args[0].c_str()); + return -1; + } } else if (rmPkgMode) { - for (const char* pkg : args) { + for (const std::string pkg : args) { if (removeNiUnderPkgRoot(pkg) != 0) { - fprintf(stderr, "Failed to get root path from [%s]\n", pkg); - return 1; + fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str()); + return -1; } } } else if (dllMode) { - for (const char* dll : args) - createNiSelect(dll, enableR2R); + for (const std::string dll : args) + createNiDll(dll, enableR2R); } else if (dirMode) { - createNiUnderDirs(args.data(), args.size(), false, enableR2R); + createNiUnderDirs(args.data(), args.size(), enableR2R); } return 0; diff --git a/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc b/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc index d7fd274..24a618a 100644 --- a/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc +++ b/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "common.h" +#include "ni_common.h" #include "log.h" #include "utils.h" @@ -51,6 +51,12 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app } if (mdValue) { + NiCommonOption option = {std::string(), std::string(), std::string()}; + if (initNICommon(&option) < 0) { + _ERR("Fail to initialize NI Common"); + return -1; + } + if (createNiUnderPkgRoot(pkgId, false) != 0) { _ERR("Failed to get root path from [%s]", pkgId); return -1; diff --git a/NativeLauncher/installer-plugin/ui-application.cc b/NativeLauncher/installer-plugin/ui-application.cc index e626265..8f1bca7 100644 --- a/NativeLauncher/installer-plugin/ui-application.cc +++ b/NativeLauncher/installer-plugin/ui-application.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "common.h" +#include "ni_common.h" #include "log.h" #ifdef LOG_TAG diff --git a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc index f3a1056..6ae5ad5 100644 --- a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc +++ b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc @@ -31,6 +31,8 @@ #include "log.h" #include "launcher.h" #include "dotnet_launcher.h" +#include "plugin_manager.h" +#include "path_manager.h" #define PLUGIN_PATH "/usr/share/dotnet.tizen/lib/libdotnet_plugin.so" @@ -88,53 +90,14 @@ CoreRuntime::CoreRuntime(const char* mode) : __coreclrLib(nullptr), __hostHandle(nullptr), __domainId(-1), - preparedFunction(nullptr), - launchFunction(nullptr), - __pluginLib(nullptr), - pluginInitialize(nullptr), - pluginPreload(nullptr), - pluginSetAppInfo(nullptr), - pluginSetCoreclrInfo(nullptr), - pluginGetDllPath(nullptr), - pluginBeforeExecute(nullptr), - pluginFinalize(nullptr), fd(0), __mode(mode) { -#define __XSTR(x) #x -#define __STR(x) __XSTR(x) - -#ifdef DEVICE_API_DIR - __deviceAPIDirectory = __STR(DEVICE_API_DIR); -#endif -#ifdef RUNTIME_DIR - __runtimeDirectory = __STR(RUNTIME_DIR); -#endif -#ifdef NATIVE_LIB_DIR - __nativeLibDirectory = __STR(NATIVE_LIB_DIR); -#endif - -#undef __STR -#undef __XSTR + _DBG("Constructor called!!"); - // support launcher plugin - if (!fileNotExist(PLUGIN_PATH)) { - __pluginLib = dlopen(PLUGIN_PATH, RTLD_NOW | RTLD_LOCAL); - if (__pluginLib) { - pluginInitialize = (plugin_initialize_ptr)dlsym(__pluginLib, "plugin_initialize"); - pluginPreload = (plugin_preload_ptr)dlsym(__pluginLib, "plugin_preload"); - pluginSetAppInfo = (plugin_set_app_info_ptr)dlsym(__pluginLib, "plugin_set_app_info"); - pluginSetCoreclrInfo = (plugin_set_coreclr_info_ptr)dlsym(__pluginLib, "plugin_set_coreclr_info"); - pluginGetDllPath = (plugin_get_dll_path_ptr)dlsym(__pluginLib, "plugin_get_dll_path"); - pluginBeforeExecute = (plugin_before_execute_ptr)dlsym(__pluginLib, "plugin_before_execute"); - pluginFinalize = (plugin_finalize_ptr)dlsym(__pluginLib, "plugin_finalize"); - } + if (runLoggingThread() < 0) { + _ERR("Failed to create logging thread"); } - - if (pluginInitialize) - pluginInitialize(mode); - - _DBG("Constructor called!!"); } CoreRuntime::~CoreRuntime() @@ -144,6 +107,16 @@ CoreRuntime::~CoreRuntime() 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 + #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. @@ -158,32 +131,23 @@ int CoreRuntime::initialize(bool standalone) putenv(const_cast("UNW_ARM_UNWIND_METHOD=6")); #endif // __arm__ - if (__deviceAPIDirectory.empty()) { - _ERR("Empty Device API Directory"); - return 1; - } else { - __deviceAPIDirectory = absolutePath(__deviceAPIDirectory); + if (initializePluginManager(__mode) < 0) { + _ERR("Failed to initialize PluginManager"); + return -1; } - if (__runtimeDirectory.empty()) { - _ERR("Empty Runtime Directory"); - return 1; - } else { - __runtimeDirectory = absolutePath(__runtimeDirectory); + if (initializePathManager(std::string(), std::string(), std::string()) < 0) { + _ERR("Failed to initialize PathManager"); + return -1; } - // set Reference API directory - __refAPIDirectory = __deviceAPIDirectory + "/ref"; - - std::string libCoreclr(concatPath(__runtimeDirectory, "libcoreclr.so")); - - _DBG("libcoreclr : %s", libCoreclr.c_str()); + 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); - return 1; + return -1; } #define CORELIB_RETURN_IF_NOSYM(type, variable, name) \ @@ -191,7 +155,7 @@ int CoreRuntime::initialize(bool standalone) variable = (type)dlsym(__coreclrLib, name); \ if (variable == nullptr) { \ _ERR(name " is not found in the libcoreclr.so"); \ - return 1; \ + return -1; \ } \ } while (0) @@ -204,39 +168,21 @@ int CoreRuntime::initialize(bool standalone) _DBG("libcoreclr dlopen and dlsym success"); - if (!standalone && pluginPreload) + if (!standalone) pluginPreload(); fd = open("/proc/self", O_DIRECTORY); - std::string path_tmp = std::string("/proc/self/fd/") + std::to_string(fd); - - std::string appRoot = path_tmp; + 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 tpa; - std::vector searchDirectories; - searchDirectories.push_back(__runtimeDirectory); - searchDirectories.push_back(__deviceAPIDirectory); - searchDirectories.push_back(__refAPIDirectory); - - if (pluginGetDllPath) { - std::string pluginPath = pluginGetDllPath(); - if (!pluginPath.empty()) { - splitPath(pluginPath, searchDirectories); - } - } - - assembliesInDirectory(searchDirectories, tpa); - - std::string nativeLibPath; - nativeLibPath = getExtraNativeLibDirs(appRoot) + ":" + appBin + ":" + appLib + ":" + __nativeLibDirectory; - + std::string tpa = getTPA(); + std::string nativeLibPath = getExtraNativeLibDirs(appRoot) + ":" + appBin + ":" + appLib + ":" + __nativeLibDirectory; 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())) { _ERR("Failed to initialize coreclr"); - return 1; + return -1; } return 0; @@ -278,8 +224,7 @@ bool CoreRuntime::initializeCoreClr(const char* appId, return false; } - if (pluginSetCoreclrInfo) - pluginSetCoreclrInfo(__hostHandle, __domainId, createDelegate); + pluginSetCoreclrInfo(__hostHandle, __domainId, createDelegate); _DBG("Initialize core clr success"); return true; @@ -291,63 +236,43 @@ void CoreRuntime::dispose() int st = shutdown(__hostHandle, __domainId); if (st < 0) _ERR("shutdown core clr fail! (0x%08x)", st); + __hostHandle = nullptr; } - if (dlclose(__coreclrLib) != 0) - _ERR("libcoreclr.so close failed"); - - __coreclrLib = nullptr; - - if (pluginFinalize) - pluginFinalize(); - - if (__pluginLib != nullptr) { - if (dlclose(__pluginLib) != 0) - _ERR("libdotnet_plugin.so close failed"); + if (__coreclrLib != nullptr) { + if (dlclose(__coreclrLib) != 0) { + _ERR("libcoreclr.so close failed"); + } - __pluginLib = nullptr; - pluginInitialize = nullptr; - pluginPreload = nullptr; - pluginSetAppInfo = nullptr; - pluginSetCoreclrInfo = nullptr; - pluginGetDllPath = nullptr; - pluginBeforeExecute = nullptr; - pluginFinalize = nullptr; + __coreclrLib = nullptr; } + finalizePluginManager(); + finalizePathManager(); + _DBG("Dotnet runtime disposed"); } int CoreRuntime::launch(const char* appId, const char* root, const char* path, int argc, char* argv[]) { - if (runLoggingThread() < 0) { - _ERR("Failed to create logging thread"); - } - if (path == nullptr) { _ERR("executable path is null"); - return 1; + return -11; } - if (fileNotExist(path)) { + if (!isFileExist(path)) { _ERR("File not exist : %s", path); - return 1; + return -1; } - if (pluginSetAppInfo) - pluginSetAppInfo(appId, path); + pluginSetAppInfo(appId, path); int fd2 = open(root, O_DIRECTORY); dup3(fd2, fd, O_CLOEXEC); if (fd2 >= 0) close(fd2); - if (pluginBeforeExecute) - pluginBeforeExecute(); - - if (runLoggingThread() < 0) { - _ERR("Failed to create logging thread"); - } + pluginBeforeExecute(); unsigned int ret = 0; int st = executeAssembly(__hostHandle, __domainId, argc, (const char**)argv, path, &ret); diff --git a/NativeLauncher/launcher/dotnet/dotnet_launcher.h b/NativeLauncher/launcher/dotnet/dotnet_launcher.h index 37b0296..82052f2 100644 --- a/NativeLauncher/launcher/dotnet/dotnet_launcher.h +++ b/NativeLauncher/launcher/dotnet/dotnet_launcher.h @@ -18,73 +18,21 @@ #define __DOTNET_LAUNCHER_H__ #include "launcher.h" - -extern "C" -{ - typedef int (*coreclr_initialize_ptr)( - const char* exePath, - const char* appDomainFriendlyName, - int propertyCount, - const char** propertyKeys, - const char** propertyValues, - void** hostHandle, - unsigned int* domainId); - - typedef int (*coreclr_execute_assembly_ptr)( - void* hostHandle, - unsigned int domainId, - int argc, - const char** argv, - const char* managedAssemblyPath, - unsigned int* exitCode); - - typedef int (*coreclr_shutdown_ptr)( - void* hostHandle, - unsigned int domainId); - - typedef int (*coreclr_create_delegate_ptr)( - void* hostHandle, - unsigned int domainId, - const char* entryPointAssemblyName, - const char* entryPointTypeName, - const char* entryPointMethodName, - void** delegate); - - typedef void (*plugin_initialize_ptr)(const char* mode); - - typedef void (*plugin_preload_ptr)(); - - typedef void (*plugin_set_app_info_ptr)( - const char* appId, - const char* managedAssemblyPath); - - typedef void (*plugin_set_coreclr_info_ptr)( - void* hostHandle, - unsigned int domainId, - coreclr_create_delegate_ptr delegateFunc); - - typedef char* (*plugin_get_dll_path_ptr)(); - - typedef void (*plugin_before_execute_ptr)(); - - typedef void (*plugin_finalize_ptr)(); -} +#include "coreclr_host.h" +#include "plugin_manager.h" namespace tizen { namespace runtime { namespace dotnetcore { -typedef void (*PreparedFunctionPtr)(); -typedef bool (*LaunchFunctionPtr)(const char* root, const char* path, int argc, char* argv[]); - -class CoreRuntime : public tizen::runtime::LauncherInterface +class CoreRuntime { public: CoreRuntime(const char* mode); ~CoreRuntime(); - int initialize(bool standalone) override; - void dispose() override; - int launch(const char* appId, const char* root, const char* path, int argc, char* argv[]) override; + int initialize(bool standalone); + 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* pinvokeProbePaths, const char* tpaList); @@ -92,24 +40,10 @@ class CoreRuntime : public tizen::runtime::LauncherInterface coreclr_execute_assembly_ptr executeAssembly; coreclr_shutdown_ptr shutdown; coreclr_create_delegate_ptr createDelegate; - std::string __deviceAPIDirectory; - std::string __runtimeDirectory; std::string __nativeLibDirectory; - std::string __refAPIDirectory; void* __coreclrLib; void* __hostHandle; unsigned int __domainId; - PreparedFunctionPtr preparedFunction; - LaunchFunctionPtr launchFunction; - // plugin function pointer - void* __pluginLib; - plugin_initialize_ptr pluginInitialize; - plugin_preload_ptr pluginPreload; - plugin_set_app_info_ptr pluginSetAppInfo; - plugin_set_coreclr_info_ptr pluginSetCoreclrInfo; - plugin_get_dll_path_ptr pluginGetDllPath; - plugin_before_execute_ptr pluginBeforeExecute; - plugin_finalize_ptr pluginFinalize; int fd; const char* __mode; }; diff --git a/NativeLauncher/launcher/launcher.cc b/NativeLauncher/launcher/launcher.cc index e0b5ed0..b0f3e1b 100644 --- a/NativeLauncher/launcher/launcher.cc +++ b/NativeLauncher/launcher/launcher.cc @@ -50,7 +50,6 @@ class LaunchpadAdapterImpl : public LaunchpadAdapter LaunchpadAdapterImpl() : callbacks(), adapter(), - launcher(nullptr), __isLaunched(false) { } int loaderMain(int argc, char* argv[]) override; @@ -61,7 +60,6 @@ class LaunchpadAdapterImpl : public LaunchpadAdapter AppInfo appInfo; loader_lifecycle_callback_s callbacks; loader_adapter_s adapter; - LauncherInterface* launcher; bool __isLaunched; std::string __launchPath; }; @@ -122,29 +120,9 @@ static void fdRemove(void *data, int fd) } } -static void preloadLibsAndWindow(bundle *extra, int type, void *userData) +static void preCreateWindow(bundle *extra, int type, void *userData) { int elmInitCnt = 0; - const char **soArray; - int len = 0; - int i; - void *handle = NULL; - - // Preload native libraries - if (extra == NULL) { - _DBG("No extra data"); - return; - } - - soArray = bundle_get_str_array(extra, "preload", &len); - - if (!soArray) - return; - - for (i = 0; i < len; i++) { - handle = dlopen(soArray[i], RTLD_NOW); - _DBG("preload %s#", soArray[i]); - } // Precreate window elmInitCnt = elm_init(__argc, __argv); @@ -167,7 +145,7 @@ int LaunchpadAdapterImpl::loaderMain(int argc, char* argv[]) __argv = argv; callbacks.create = [](bundle *extra, int type, void *userData) { ecore_init(); - preloadLibsAndWindow(extra, type, userData); + preCreateWindow(extra, type, userData); WITH_SELF(userData) { if (self->onCreate != nullptr) self->onCreate(); diff --git a/NativeLauncher/launcher/launcher.h b/NativeLauncher/launcher/launcher.h index 38934b4..e48f318 100644 --- a/NativeLauncher/launcher/launcher.h +++ b/NativeLauncher/launcher/launcher.h @@ -23,14 +23,6 @@ namespace tizen { namespace runtime { -class LauncherInterface -{ - public: - virtual int initialize(bool standalone) = 0; - virtual void dispose() = 0; - virtual int launch(const char* appId, const char* root, const char* path, int argc, char* argv[]) = 0; -}; - struct AppInfo { std::string root; std::string path; diff --git a/NativeLauncher/launcher/main.cc b/NativeLauncher/launcher/main.cc index e49010e..9522496 100644 --- a/NativeLauncher/launcher/main.cc +++ b/NativeLauncher/launcher/main.cc @@ -28,18 +28,8 @@ #include #include -#define __XSTR(x) #x -#define __STR(x) __XSTR(x) - -#ifndef VERSION -#define LAUNCHER_VERSION_STR "-Unknown-" -#else -#define LAUNCHER_VERSION_STR __STR(VERSION) -#endif - #define CMD_LINE_SIZE 24 // sizeof("/usr/bin/dotnet-launcher") -static std::string VersionOption("--version"); static std::string StandaloneOption("--standalone"); extern "C" int realMain(int argc, char *argv[], const char* mode) @@ -52,10 +42,7 @@ extern "C" int realMain(int argc, char *argv[], const char* mode) // start index 1 to avoid passing executable name "dotnet-launcher" as a parameter for (i = 1; i < argc; i++) { - if (VersionOption.compare(argv[i]) == 0) { - printf("Dotnet launcher Version %s\n", LAUNCHER_VERSION_STR); - return 0; - } else if (StandaloneOption.compare(argv[i]) == 0) { + if (StandaloneOption.compare(argv[i]) == 0) { standalone = true; if (i > argc-1) { @@ -69,14 +56,11 @@ extern "C" int realMain(int argc, char *argv[], const char* mode) } } - using tizen::runtime::LauncherInterface; using tizen::runtime::Launchpad; using tizen::runtime::AppInfo; - std::unique_ptr runtime; - using tizen::runtime::dotnetcore::CoreRuntime; - std::unique_ptr coreRuntime(new CoreRuntime(mode)); - runtime = std::move(coreRuntime); + + std::unique_ptr runtime(new CoreRuntime(mode)); if (standalone) { _DBG("##### Run it standalone #########"); @@ -140,7 +124,6 @@ extern "C" int realMain(int argc, char *argv[], const char* mode) } } - runtime->dispose(); return 0; } diff --git a/NativeLauncher/util/path_manager.cc b/NativeLauncher/util/path_manager.cc new file mode 100644 index 0000000..7ca1e3e --- /dev/null +++ b/NativeLauncher/util/path_manager.cc @@ -0,0 +1,138 @@ +/* + * 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 +#include +#include +#include + +#include "utils.h" +#include "plugin_manager.h" +#include "log.h" + +static const char* __TIZEN_API_PATH_KEY = "db/dotnet/tizen_api_path"; + +#define __XSTR(x) #x +#define __STR(x) __XSTR(x) +static const char* __DEVICE_API_DIR = __STR(DEVICE_API_DIR); +static const char* __RUNTIME_DIR = __STR(RUNTIME_DIR); +#undef __STR +#undef __XSTR + +typedef struct DllPath { + std::string runtime_dir; + std::string tizenfx_dir; + std::string tizenfx_ref_dir; + std::vector extra_dirs; +} DllPath; + +static DllPath* __dllPath = NULL; +static std::string __tpa; + +// on success, return 0. otherwise return -1. +int initializePathManager(const std::string& runtimeDir, const std::string& tizenFXDir, const std::string& extraDir) +{ + + __dllPath = (DllPath*)calloc(sizeof(DllPath), 1); + if (!__dllPath) { + fprintf(stderr, "fail to allocate memory for dll path structure\n"); + return -1; + } + + if (!runtimeDir.empty()) { + __dllPath->runtime_dir = absolutePath(runtimeDir); + } else { + __dllPath->runtime_dir = absolutePath(__RUNTIME_DIR); + } + + if (!tizenFXDir.empty()) { + __dllPath->tizenfx_dir = absolutePath(tizenFXDir); + } else { + char* tmp = vconf_get_str(__TIZEN_API_PATH_KEY); + if (tmp) { + __dllPath->tizenfx_dir = std::string(tmp); + _DBG("Device API Directory is set by vconf : %s", tmp); + } else { + __dllPath->tizenfx_dir = absolutePath(__DEVICE_API_DIR); + } + } + + __dllPath->tizenfx_ref_dir = __dllPath->tizenfx_dir + "/ref"; + + // ":" seperated extra directories + if (!extraDir.empty()) { + splitPath(extraDir, __dllPath->extra_dirs); + } else { + if (pluginGetDllPath()) { + std::string pluginPath(pluginGetDllPath()); + if (!pluginPath.empty()) { + splitPath(pluginPath, __dllPath->extra_dirs); + } + } + } + + return 0; +} + +void finalizePathManager() +{ + if (__dllPath) { + free(__dllPath); + __dllPath = NULL; + } +} + +std::string getRuntimeDir() +{ + return __dllPath->runtime_dir; +} + +std::string getTizenFXDir() +{ + return __dllPath->tizenfx_dir; +} + +std::string getTizenFXRefDir() +{ + return __dllPath->tizenfx_ref_dir; +} + +std::vector getExtraDirs() +{ + return __dllPath->extra_dirs; +} + +std::string getTPA() +{ + if (!__tpa.empty()) { + return __tpa; + } + + std::vector tpaDir; + + if (__dllPath == NULL) { + return std::string(""); + } + + tpaDir.push_back(getRuntimeDir()); + tpaDir.push_back(getTizenFXDir()); + tpaDir.push_back(getTizenFXRefDir()); + tpaDir.insert(tpaDir.end(), getExtraDirs().begin(), getExtraDirs().end()); + assembliesInDirectory(tpaDir, __tpa); + + return __tpa; +} + diff --git a/NativeLauncher/util/path_manager.h b/NativeLauncher/util/path_manager.h new file mode 100644 index 0000000..72dc042 --- /dev/null +++ b/NativeLauncher/util/path_manager.h @@ -0,0 +1,30 @@ +/* + * 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 __DLL_PATH_MANAGER_H__ +#define __DLL_PATH_MANAGER_H__ + +int initializePathManager(const std::string& runtimeDir, const std::string& tizenFXDir, const std::string& extraDir); +void finalizePathManager(); + +std::string getRuntimeDir(); +std::string getTizenFXDir(); +std::string getTizenFXRefDir(); +std::string getExtraDirs(); + +std::string getTPA(); + +#endif /* __DLL_PATH_MANAGER_H__ */ \ No newline at end of file diff --git a/NativeLauncher/util/plugin_manager.cc b/NativeLauncher/util/plugin_manager.cc new file mode 100644 index 0000000..563eaa3 --- /dev/null +++ b/NativeLauncher/util/plugin_manager.cc @@ -0,0 +1,105 @@ +/* + * 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 + +#include "plugin_manager.h" +#include "utils.h" +#include "log.h" + +static PluginFunc* __pluginFunc = NULL; +static void* __pluginLib; + +#define PLUGIN_PATH "/usr/share/dotnet.tizen/lib/libdotnet_plugin.so" + +int initializePluginManager(const char* mode) +{ + if (isFileExist(PLUGIN_PATH)) { + __pluginLib = dlopen(PLUGIN_PATH, RTLD_NOW | RTLD_LOCAL); + if (__pluginLib) { + __pluginFunc = (PluginFunc*)calloc(sizeof(PluginFunc), 1); + if (!__pluginFunc) { + fprintf(stderr, "fail to allocate memory for plugin function structure\n"); + return -1; + } + __pluginFunc->initialize = (plugin_initialize_ptr)dlsym(__pluginLib, "plugin_initialize"); + __pluginFunc->preload = (plugin_preload_ptr)dlsym(__pluginLib, "plugin_preload"); + __pluginFunc->set_app_info = (plugin_set_app_info_ptr)dlsym(__pluginLib, "plugin_set_app_info"); + __pluginFunc->set_coreclr_info = (plugin_set_coreclr_info_ptr)dlsym(__pluginLib, "plugin_set_coreclr_info"); + __pluginFunc->get_dll_path = (plugin_get_dll_path_ptr)dlsym(__pluginLib, "plugin_get_dll_path"); + __pluginFunc->before_execute = (plugin_before_execute_ptr)dlsym(__pluginLib, "plugin_before_execute"); + __pluginFunc->finalize = (plugin_finalize_ptr)dlsym(__pluginLib, "plugin_finalize"); + } + + if (__pluginFunc->initialize) + __pluginFunc->initialize(mode); + } + + return 0; +} + +void finalizePluginManager() +{ + if (__pluginFunc) { + if (__pluginFunc->finalize) { + __pluginFunc->finalize(); + } + free(__pluginFunc); + __pluginFunc = NULL; + } + + if (__pluginLib) { + dlclose(__pluginLib); + __pluginLib = NULL; + } +} + +void pluginPreload() +{ + if (__pluginFunc && __pluginFunc->preload) { + __pluginFunc->preload(); + } +} + +void pluginSetAppInfo(const char* appId, const char* managedAssemblyPath) +{ + if (__pluginFunc && __pluginFunc->set_app_info) { + __pluginFunc->set_app_info(appId, managedAssemblyPath); + } +} + +void pluginSetCoreclrInfo(void* hostHandle, unsigned int domainId, coreclr_create_delegate_ptr delegateFunc) +{ + if (__pluginFunc && __pluginFunc->set_coreclr_info) { + __pluginFunc->set_coreclr_info(hostHandle, domainId, delegateFunc); + } +} + +char* pluginGetDllPath() +{ + if (__pluginFunc && __pluginFunc->get_dll_path) { + return __pluginFunc->get_dll_path(); + } else { + return NULL; + } +} + +void pluginBeforeExecute() +{ + if (__pluginFunc && __pluginFunc->before_execute) { + __pluginFunc->before_execute(); + } +} + diff --git a/NativeLauncher/util/utils.cc b/NativeLauncher/util/utils.cc index 4016ac5..76ac831 100644 --- a/NativeLauncher/util/utils.cc +++ b/NativeLauncher/util/utils.cc @@ -31,19 +31,12 @@ #include #include "utils.h" +#include "path_manager.h" #include "log.h" static pthread_t loggingThread; -bool iCompare(const std::string& a, const std::string& b) -{ - return a.length() == b.length() && - std::equal(b.begin(), b.end(), a.begin(), - [](unsigned char a, unsigned char b) - { return std::tolower(a) == std::tolower(b); }); -} - -bool iCompare(const std::string& a, int aOffset, const std::string& b, int bOffset, int length) +static bool iCompare(const std::string& a, int aOffset, const std::string& b, int bOffset, int length) { return static_cast(a.length()) - length >= aOffset && static_cast(b.length()) - length >= bOffset && @@ -54,8 +47,9 @@ bool iCompare(const std::string& a, int aOffset, const std::string& b, int bOffs bool isManagedAssembly(const std::string& fileName) { - return iCompare(fileName, fileName.size()-4, ".dll", 0, 4) || - iCompare(fileName, fileName.size()-4, ".exe", 0, 4); + return (iCompare(fileName, fileName.size()-4, ".dll", 0, 4) || + iCompare(fileName, fileName.size()-4, ".exe", 0, 4)) && + !isNativeImage(fileName); } bool isNativeImage(const std::string& fileName) @@ -98,16 +92,6 @@ void splitPath(const std::string& path, std::vector& out) } } -void appendPath(std::string& path1, const std::string& path2) -{ - if (path1.back() == PATH_SEPARATOR) { - path1.append(path2); - } else { - path1 += PATH_SEPARATOR; - path1.append(path2); - } -} - std::string absolutePath(const std::string& path) { std::string absPath; @@ -128,56 +112,12 @@ std::string baseName(const std::string& path) return path; } -bool endWithIgnoreCase(const std::string& str1, const std::string& str2, std::string& fileName) -{ - std::string::size_type len1 = str1.length(); - std::string::size_type len2 = str2.length(); - if (len2 > len1) - return false; - - int i = 0; - bool result = std::all_of(str1.cend() - len2, str1.end(), - [&i, &str2] (char x) { - return std::tolower(x) == std::tolower(str2[i++]); - }); - if (result) - fileName = str1.substr(0, len1 - len2); - - return result; -} - -bool fileNotExist(const std::string& path) +bool isFileExist(const std::string& path) { struct stat sb; - return stat(path.c_str(), &sb) != 0; + return stat(path.c_str(), &sb) == 0; } -#ifdef NOT_USE_FUNCTION -static bool extCheckAndGetFileNameIfExist(const std::string& dir, const std::string& ext, struct dirent* entry, std::string& fileName) -{ - std::string fName(entry->d_name); - if (fName.length() < ext.length() || - fHame.compare(fName.length() - ext.length(), ext.length(), ext) != 0) { - return false; - } - - std::string fullName = concatPath(dir, entry->d_name); - switch (entry->d_type) { - case DT_REG: break; - case DT_LNK: - case DT_UNKNOWN: - if (fileNotExist(fullName)) - return false; - default: - return false; - } - - fileName = fullName; - - return true; -} -#endif - std::string stripNiDLL(const std::string& path) { std::string niPath(path); @@ -193,57 +133,19 @@ std::string stripNiDLL(const std::string& path) return niPath; } -std::string joinStrings(const std::vector& strings, const char* const delimeter) -{ - switch (strings.size()) { - case 0: - return ""; - case 1: - return strings[0]; - default: - std::ostringstream os; - std::copy(strings.begin(), strings.end()-1, std::ostream_iterator(os, delimeter)); - os << *strings.rbegin(); - return os.str(); - } -} - -struct AssemblyFile { - std::string noExt; - std::string ext; -}; - -bool operator == (const AssemblyFile& lhs, const AssemblyFile& rhs) -{ - return lhs.noExt == rhs.noExt && lhs.ext == rhs.ext; -} - -namespace std { - template<> - struct hash { - std::size_t operator () (const AssemblyFile& f) const { - const std::size_t h1 = std::hash{}(f.noExt); - const std::size_t h2 = std::hash{}(f.ext); - - return h1 ^ (h2 << 1); - } - }; -} - void assembliesInDirectory(const std::vector& directories, std::string& tpaList) { std::map assemblyList; std::map tmpList; - auto reader = [&assemblyList, &tmpList] (const char* path, const char* name) { - std::string pathStr(path); - if (isManagedAssembly(pathStr)) { + auto reader = [&assemblyList, &tmpList] (const std::string& path, const char* name) { + if (isManagedAssembly(path) || isNativeImage(path)) { std::string dllName = stripNiDLL(name); std::pair::iterator, bool> ret; - ret = tmpList.insert(std::pair(dllName, pathStr)); + ret = tmpList.insert(std::pair(dllName, path)); if (ret.second == false) { - if (isNativeImage(pathStr)) - tmpList[dllName] = pathStr; + if (isNativeImage(path)) + tmpList[dllName] = path; } } }; @@ -263,13 +165,13 @@ void assembliesInDirectory(const std::vector& directories, std::str tpaList.pop_back(); } -void scanFilesInDir(const char* directory, FileReader reader, unsigned int depth) +void scanFilesInDir(const std::string& directory, FileReader reader, unsigned int depth) { DIR *dir; struct dirent* entry; bool isDir; - dir = opendir(directory); + dir = opendir(directory.c_str()); if (dir == nullptr) return; @@ -296,7 +198,7 @@ void scanFilesInDir(const char* directory, FileReader reader, unsigned int depth continue; } if (!isDir) - reader(path.c_str(), entry->d_name); + reader(path, entry->d_name); else if (depth > 1 && strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) innerDirectories.push_back(path); } @@ -308,12 +210,30 @@ void scanFilesInDir(const char* directory, FileReader reader, unsigned int depth closedir(dir); } +static int __pfd[2]; + static void *stdlog(void*) { - int pfd[2]; ssize_t readSize; char buf[1024]; + while ((readSize = read(__pfd[0], buf, sizeof buf - 1)) > 0) { + if (buf[readSize - 1] == '\n') { + --readSize; + } + + buf[readSize] = 0; + + _LOGX("%s", buf); + } + + close(__pfd[0]); + + return 0; +} + +int runLoggingThread() +{ if (setvbuf(stdout, NULL, _IOLBF, 0) < 0) { _DBG("fail to make stdout line-buffered"); return 0; @@ -325,39 +245,25 @@ static void *stdlog(void*) } /* create the pipe and redirect stdout and stderr */ - if (pipe(pfd) < 0) { + if (pipe(__pfd) < 0) { _DBG("fail to create pipe for logging"); return 0; } - if (dup2(pfd[1], fileno(stdout)) == -1) { + // stdout + if (dup2(__pfd[1], 1) == -1) { _DBG("fail to duplicate fd to stdout"); return 0; } - if (dup2(pfd[1], fileno(stderr)) == -1) { + // stderr + if (dup2(__pfd[1], 2) == -1) { _DBG("fail to duplicate fd to stderr"); return 0; } - close(pfd[1]); - - while ((readSize = read(pfd[0], buf, sizeof buf - 1)) > 0) { - if (buf[readSize - 1] == '\n') { - --readSize; - } - - buf[readSize] = 0; - - _LOGX("%s", buf); - } - - close(pfd[0]); - - return 0; -} + close(__pfd[1]); -int runLoggingThread() { /* spawn the logging thread */ if (pthread_create(&loggingThread, 0, stdlog, 0) != 0) { _DBG("fail to create pthread"); diff --git a/packaging/dotnet-launcher.spec b/packaging/dotnet-launcher.spec index 19c42ff..9f3e611 100644 --- a/packaging/dotnet-launcher.spec +++ b/packaging/dotnet-launcher.spec @@ -1,6 +1,6 @@ Name: dotnet-launcher Summary: Launchpad plugin for dotnet apps -Version: 1.1.0 +Version: 2.1.0 Release: 1 Group: Application Framework/Application State Management License: Apache-2.0 @@ -17,6 +17,7 @@ BuildRequires: pkgconfig(pkgmgr-info) BuildRequires: pkgconfig(pkgmgr-installer) BuildRequires: pkgconfig(elementary) BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(libsmack) BuildRequires: aul-devel BuildRequires: dotnet-build-tools @@ -35,10 +36,8 @@ Requires(postun): /usr/bin/systemctl Requires(preun): /usr/bin/systemctl %define _loaderdir %{_prefix}/share/aul -%define _configdir /etc %define _device_api_dir %{dotnet_assembly_path} %define _runtime_dir /usr/share/dotnet/shared/Microsoft.NETCore.App/2.0.0 -%define _install_plugin_dir /usr/etc/package-manager/parserlib %define _install_mdplugin_dir /etc/package-manager/parserlib/metadata %define _native_lib_dir /usr/share/dotnet.tizen/lib @@ -47,6 +46,13 @@ ExcludeArch: aarch64 %description Launchpad plugin for launching dotnet apps +%package devel +Summary: Libraries and Header Files for dotnet-launcher plugins and AOTC tools +Requires: %{name} = %{version} + +%description devel +This package contains library and header files needed to develop plugins for dotnet-launcher +and AOTC tools. %prep %setup -q @@ -70,16 +76,14 @@ cmake \ -DCMAKE_CXX_COMPILER=clang++ \ -DASAN_ENABLED=TRUE \ %endif - -DPACKAGE_NAME=%{name} \ -DLIBDIR=%{_libdir} \ -DBINDIR=%{_bindir} \ + -DINCLUDEDIR=%{_includedir} \ -DLOADERDIR=%{_loaderdir} \ - -DCONFIGDIR=%{_configdir} \ -DCMAKE_BUILD_TYPE=%{_dotnet_build_conf} \ -DDEVICE_API_DIR=%{_device_api_dir} \ -DRUNTIME_DIR=%{_runtime_dir} \ -DCROSSGEN_PATH=%{_device_api_dir}/crossgen \ - -DINSTALL_PLUGIN_DIR=%{_install_plugin_dir} \ -DINSTALL_MDPLUGIN_DIR=%{_install_mdplugin_dir} \ -DVERSION=%{version} \ -DNATIVE_LIB_DIR=%{_native_lib_dir} \ @@ -101,7 +105,18 @@ ln -sf %{_libdir}/libsqlite3.so.0 %{buildroot}%{_native_lib_dir}/libsqlite3.so %{_loaderdir}/dotnet.debugger %{_native_lib_dir}/libsqlite3.so %{_bindir}/nitool -#%{_install_plugin_dir}/libui-application.so %{_install_mdplugin_dir}/libprefer_dotnet_aot_plugin.so %{_bindir}/dotnet-launcher +%{_libdir}/libdotnet_launcher_util.so +%{_libdir}/libni_common.so + +%files devel +%manifest dotnet-launcher.manifest +%defattr(-,root,root,-) +%{_includedir}/ni_common.h +%{_includedir}/dotnet_launcher_plugin.h +%{_includedir}/coreclr_host.h +%{_libdir}/libdotnet_launcher_util.so +%{_libdir}/libni_common.so +%{_libdir}/pkgconfig/dotnet-launcher.pc -- 2.7.4 From 8125926c54715f461e951e6aae551d850a6594bc Mon Sep 17 00:00:00 2001 From: Woongsuk Cho Date: Thu, 28 Jun 2018 10:03:20 +0900 Subject: [PATCH 06/16] add comment for header and fix some wrong return value Change-Id: I53c885ed0f3ffbd4c95321dca57a72e92632b387 --- NativeLauncher/inc/dotnet_launcher_plugin.h | 57 ++++++++++++++++++----- NativeLauncher/inc/plugin_manager.h | 18 +++++--- NativeLauncher/inc/utils.h | 70 +++++++++++++++++++++++++++-- NativeLauncher/util/utils.cc | 11 ++--- 4 files changed, 129 insertions(+), 27 deletions(-) diff --git a/NativeLauncher/inc/dotnet_launcher_plugin.h b/NativeLauncher/inc/dotnet_launcher_plugin.h index 4e75917..21967c4 100644 --- a/NativeLauncher/inc/dotnet_launcher_plugin.h +++ b/NativeLauncher/inc/dotnet_launcher_plugin.h @@ -21,18 +21,51 @@ extern "C" { - typedef void (*plugin_initialize_ptr)(const char* mode); - typedef void (*plugin_preload_ptr)(); - typedef void (*plugin_set_app_info_ptr)( - const char* appId, - const char* managedAssemblyPath); - typedef void (*plugin_set_coreclr_info_ptr)( - void* hostHandle, - unsigned int domainId, - coreclr_create_delegate_ptr delegateFunc); - typedef char* (*plugin_get_dll_path_ptr)(); - typedef void (*plugin_before_execute_ptr)(); - typedef void (*plugin_finalize_ptr)(); + /** + * @brief initialize plugin code + * @param[in] mode mode of plugin ("default", "inhouse", etc) + */ + void plugin_initialize(const char* mode); + + /** + * @brief preload libraries. this fuction is called in the candidate process only + */ + void plugin_preload(); + + /** + * @brief set appInfo to plugin + * @param[in] appID application ID to launch + * @param[in] assemblyPath assembly path which has entry point + */ + void plugin_set_app_info(const char* appId, + const char* assemblyPath); + + /** + * @brief set coreclr info to plugin + * @param[in] hostHandle host handle of coreclr + * @param[in] domainId current domain ID + * @param[in] coreclr_create_delegate_ptr function pointer of coreclr_create_delegate + * delegate function can be used to preload managed code + */ + void plugin_set_coreclr_info(void* hostHandle, + unsigned int domainId, + coreclr_create_delegate_ptr delegateFunc); + + /** + * @brief return additional pathes to find platform assembly. + * @return ":" seperated pathes + */ + char* plugin_get_dll_path(); + + /** + * @brief function will be called before invoking managed code + */ + void plugin_before_execute(); + + /** + * @brief function will be called when application is terminated + */ + void plugin_finalize(); } #endif /* __DOTNET_LAUNCHER_PLUGIN_H__ */ diff --git a/NativeLauncher/inc/plugin_manager.h b/NativeLauncher/inc/plugin_manager.h index 94e1798..0e8cacd 100644 --- a/NativeLauncher/inc/plugin_manager.h +++ b/NativeLauncher/inc/plugin_manager.h @@ -17,12 +17,20 @@ #ifndef __PLUGIN_MANAGER_H__ #define __PLUGIN_MANAGER_H__ -#include "dotnet_launcher_plugin.h" #include "coreclr_host.h" -extern "C" -{ - +typedef void (*plugin_initialize_ptr)(const char* mode); +typedef void (*plugin_preload_ptr)(); +typedef void (*plugin_set_app_info_ptr)( + const char* appId, + const char* managedAssemblyPath); +typedef void (*plugin_set_coreclr_info_ptr)( + void* hostHandle, + unsigned int domainId, + coreclr_create_delegate_ptr delegateFunc); +typedef char* (*plugin_get_dll_path_ptr)(); +typedef void (*plugin_before_execute_ptr)(); +typedef void (*plugin_finalize_ptr)(); typedef struct PluginFunc { plugin_initialize_ptr initialize; @@ -45,6 +53,4 @@ void pluginBeforeExecute(); int initializePluginManager(const char* mode); void finalizePluginManager(); -} - #endif /* __PLUGIN_MANAGER_H__ */ diff --git a/NativeLauncher/inc/utils.h b/NativeLauncher/inc/utils.h index 534be8b..e43b63a 100644 --- a/NativeLauncher/inc/utils.h +++ b/NativeLauncher/inc/utils.h @@ -20,29 +20,91 @@ #include #include #include -#include #ifndef PATH_SEPARATOR #define PATH_SEPARATOR '/' #endif +/** + * @brief get current executable path + * return std::string path + */ std::string readSelfPath(); +/** + * @brief concat path with PATH_SEPARATOR + * @param[in] destination path + * @param[in] source path + * return std::string result path + */ std::string concatPath(const std::string& path1, const std::string& path2); + +/** + * @brief get absolute Path + * @param[in] source path + * return std::string result path + */ std::string absolutePath(const std::string& path); + +/** + * @brief get the directory of file + * @param[in] source path + * return std::string result path + */ std::string baseName(const std::string& path); + +/** + * @brief split path with ":" delimiter and put that in the vector + * @param[in] source path + * @param[out] string vector + */ void splitPath(const std::string& path, std::vector& out); -void appendPath(std::string& path1, const std::string& path2); +/** + * @brief check file is exist + * @param[in] source path + * @return bool + */ bool isFileExist(const std::string& path); -bool isManagedAssembly(const std::string& fileName); -bool isNativeImage(const std::string& fileName); +/** + * @brief check the file is managed assembly or not. + * @param[in] file path + * @return return true when the file is managed assembly. + * otherwise return false including native image case. + */ +bool isManagedAssembly(const std::string& filePath); + +/** + * @brief check the file is native image or not. + * @param[in] file path + * @return return true when the file is native image. + */ +bool isNativeImage(const std::string& filePath); +/** + * @brief find assembly files in the directories + * @param[in] directories + * @param[out] ":" seperated assembly path list + */ void assembliesInDirectory(const std::vector& directories, std::string& tpaList); +/** + * @brief function pointer for file reader + */ typedef std::function FileReader; + +/** + * @brief scan files in the given directory and run file reader function for that + * @param[in] directory + * @param[in] file reader function + * @param[in] scan depth + */ void scanFilesInDir(const std::string& directory, FileReader reader, unsigned int depth); +/** + * @brief start logging thread to bypass stderr and stdout to dlog + * @return return 0 when success, otherwise return negative value. + */ int runLoggingThread(); #endif /* __UTILS_H__ */ diff --git a/NativeLauncher/util/utils.cc b/NativeLauncher/util/utils.cc index 76ac831..62f7b9c 100644 --- a/NativeLauncher/util/utils.cc +++ b/NativeLauncher/util/utils.cc @@ -29,6 +29,7 @@ #include #include #include +#include #include "utils.h" #include "path_manager.h" @@ -236,30 +237,30 @@ int runLoggingThread() { if (setvbuf(stdout, NULL, _IOLBF, 0) < 0) { _DBG("fail to make stdout line-buffered"); - return 0; + return -1; } if (setvbuf(stderr, NULL, _IONBF, 0) < 0) { _DBG("make stderr unbuffered"); - return 0; + return -1; } /* create the pipe and redirect stdout and stderr */ if (pipe(__pfd) < 0) { _DBG("fail to create pipe for logging"); - return 0; + return -1; } // stdout if (dup2(__pfd[1], 1) == -1) { _DBG("fail to duplicate fd to stdout"); - return 0; + return -1; } // stderr if (dup2(__pfd[1], 2) == -1) { _DBG("fail to duplicate fd to stderr"); - return 0; + return -1; } close(__pfd[1]); -- 2.7.4 From 8cb3f09416f3808b355d2ddb8530f039ae70c15d Mon Sep 17 00:00:00 2001 From: Woongsuk Cho Date: Thu, 28 Jun 2018 10:53:14 +0900 Subject: [PATCH 07/16] ignore small value for usleep to avoid SVACE issue Change-Id: I2012379154c5a775dc1717f5b2a8c54bb929a8aa --- NativeLauncher/installer-plugin/ni_common.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NativeLauncher/installer-plugin/ni_common.cc b/NativeLauncher/installer-plugin/ni_common.cc index 7bdaa2f..97725a3 100644 --- a/NativeLauncher/installer-plugin/ni_common.cc +++ b/NativeLauncher/installer-plugin/ni_common.cc @@ -61,7 +61,8 @@ static int __interval = 0; static void waitInterval() { - if (__interval > 0) { + // by the recommand, ignore small value for performance. + if (__interval > 10000) { fprintf(stderr, "sleep %d usec\n", __interval); usleep(__interval); } -- 2.7.4 From ca5879574009fe7bf53a1d5e920d6e43fc6b6be1 Mon Sep 17 00:00:00 2001 From: Woongsuk Cho Date: Thu, 28 Jun 2018 10:54:35 +0900 Subject: [PATCH 08/16] change runtime directory from 2.0.0 to 2.1.0 Change-Id: I178702eba570cffa25a38b643d9f407b80fa7969 --- packaging/dotnet-launcher.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/dotnet-launcher.spec b/packaging/dotnet-launcher.spec index 9f3e611..766e929 100644 --- a/packaging/dotnet-launcher.spec +++ b/packaging/dotnet-launcher.spec @@ -37,7 +37,7 @@ Requires(preun): /usr/bin/systemctl %define _loaderdir %{_prefix}/share/aul %define _device_api_dir %{dotnet_assembly_path} -%define _runtime_dir /usr/share/dotnet/shared/Microsoft.NETCore.App/2.0.0 +%define _runtime_dir /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.0 %define _install_mdplugin_dir /etc/package-manager/parserlib/metadata %define _native_lib_dir /usr/share/dotnet.tizen/lib -- 2.7.4 From dedf6e1c0a217f9a0fdf4ef949d8539b7f20b661 Mon Sep 17 00:00:00 2001 From: Woongsuk Cho Date: Thu, 28 Jun 2018 16:21:02 +0900 Subject: [PATCH 09/16] remove unnecessary log Change-Id: I1213e18d3bfb49f4969e3072b7619a5ef0918a9b --- NativeLauncher/installer-plugin/ni_common.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/NativeLauncher/installer-plugin/ni_common.cc b/NativeLauncher/installer-plugin/ni_common.cc index 97725a3..8c200ce 100644 --- a/NativeLauncher/installer-plugin/ni_common.cc +++ b/NativeLauncher/installer-plugin/ni_common.cc @@ -336,7 +336,6 @@ void createNiUnderDirs(const std::string rootPaths[], int count, const std::stri fprintf(stderr, "Already [%s] file is exist\n", niPath.c_str()); return; } - fprintf(stderr, "path [%s], appPath[%s]\n", path.c_str(), appPaths.c_str()); crossgen(path, appPaths.c_str(), enableR2R); if (niExist(path, niPath)) { if (cb != nullptr) -- 2.7.4 From 56a6a6713d59cfef9b03c482ce9291b39c9c075e Mon Sep 17 00:00:00 2001 From: "j-h.choi" Date: Fri, 6 Jul 2018 09:49:55 +0900 Subject: [PATCH 10/16] [Tizen] Provide a symlink to installed Microsoft.NETCore.App version https://review.tizen.org/gerrit/#/c/183471/ Change-Id: I540c3872b640b03a6c7fc8799f4b3a8a3fc8cfb5 --- packaging/dotnet-launcher.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/dotnet-launcher.spec b/packaging/dotnet-launcher.spec index 766e929..572ffb8 100644 --- a/packaging/dotnet-launcher.spec +++ b/packaging/dotnet-launcher.spec @@ -37,7 +37,7 @@ Requires(preun): /usr/bin/systemctl %define _loaderdir %{_prefix}/share/aul %define _device_api_dir %{dotnet_assembly_path} -%define _runtime_dir /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.0 +%define _runtime_dir /usr/share/dotnet.tizen/netcoreapp %define _install_mdplugin_dir /etc/package-manager/parserlib/metadata %define _native_lib_dir /usr/share/dotnet.tizen/lib -- 2.7.4 From 3ae94112942c59996f0132b7879711d318cfd44a Mon Sep 17 00:00:00 2001 From: Woongsuk Cho Date: Tue, 10 Jul 2018 10:17:08 +0900 Subject: [PATCH 11/16] use new operation instead of calloc to avoid crash Change-Id: I6cc0995be7fb08737ce47aa8712f5883ae072e70 --- NativeLauncher/util/path_manager.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/NativeLauncher/util/path_manager.cc b/NativeLauncher/util/path_manager.cc index 7ca1e3e..cc42e88 100644 --- a/NativeLauncher/util/path_manager.cc +++ b/NativeLauncher/util/path_manager.cc @@ -39,14 +39,13 @@ typedef struct DllPath { std::vector extra_dirs; } DllPath; -static DllPath* __dllPath = NULL; +static DllPath* __dllPath = nullptr; static std::string __tpa; // on success, return 0. otherwise return -1. int initializePathManager(const std::string& runtimeDir, const std::string& tizenFXDir, const std::string& extraDir) { - - __dllPath = (DllPath*)calloc(sizeof(DllPath), 1); + __dllPath = new DllPath(); if (!__dllPath) { fprintf(stderr, "fail to allocate memory for dll path structure\n"); return -1; @@ -90,7 +89,7 @@ int initializePathManager(const std::string& runtimeDir, const std::string& tize void finalizePathManager() { if (__dllPath) { - free(__dllPath); + delete __dllPath; __dllPath = NULL; } } -- 2.7.4 From d30d10e3a78ba764d298939859415001d697aa38 Mon Sep 17 00:00:00 2001 From: Woongsuk Cho Date: Tue, 10 Jul 2018 10:18:40 +0900 Subject: [PATCH 12/16] check runtime initialize before launch application to avoid crash Change-Id: I142bd6f5ab42414d0f9183535751143a3e20d3e3 --- NativeLauncher/launcher/dotnet/dotnet_launcher.cc | 12 ++++++++++-- NativeLauncher/launcher/dotnet/dotnet_launcher.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc index 6ae5ad5..2b2006c 100644 --- a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc +++ b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc @@ -91,7 +91,8 @@ CoreRuntime::CoreRuntime(const char* mode) : __hostHandle(nullptr), __domainId(-1), fd(0), - __mode(mode) + __mode(mode), + __initialized(false) { _DBG("Constructor called!!"); @@ -185,6 +186,8 @@ int CoreRuntime::initialize(bool standalone) return -1; } + __initialized = true; + return 0; } @@ -255,9 +258,14 @@ void CoreRuntime::dispose() 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 -11; + return -1; } if (!isFileExist(path)) { diff --git a/NativeLauncher/launcher/dotnet/dotnet_launcher.h b/NativeLauncher/launcher/dotnet/dotnet_launcher.h index 82052f2..647640a 100644 --- a/NativeLauncher/launcher/dotnet/dotnet_launcher.h +++ b/NativeLauncher/launcher/dotnet/dotnet_launcher.h @@ -46,6 +46,7 @@ class CoreRuntime unsigned int __domainId; int fd; const char* __mode; + bool __initialized; }; } // dotnetcore -- 2.7.4 From 97d13822a6b55b5b1418df892811b5795f6ee5c3 Mon Sep 17 00:00:00 2001 From: Woongsuk Cho Date: Wed, 11 Jul 2018 10:35:15 +0900 Subject: [PATCH 13/16] bug-fix : support plugin path for tpa Change-Id: I98c0f768dcc6d135cdbc6bc2b3e9682d78cbd933 --- NativeLauncher/util/path_manager.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/NativeLauncher/util/path_manager.cc b/NativeLauncher/util/path_manager.cc index cc42e88..99446ed 100644 --- a/NativeLauncher/util/path_manager.cc +++ b/NativeLauncher/util/path_manager.cc @@ -75,11 +75,9 @@ int initializePathManager(const std::string& runtimeDir, const std::string& tize if (!extraDir.empty()) { splitPath(extraDir, __dllPath->extra_dirs); } else { - if (pluginGetDllPath()) { - std::string pluginPath(pluginGetDllPath()); - if (!pluginPath.empty()) { - splitPath(pluginPath, __dllPath->extra_dirs); - } + char* extraPath = pluginGetDllPath(); + if (extraPath) { + splitPath(extraPath, __dllPath->extra_dirs); } } @@ -129,7 +127,7 @@ std::string getTPA() tpaDir.push_back(getRuntimeDir()); tpaDir.push_back(getTizenFXDir()); tpaDir.push_back(getTizenFXRefDir()); - tpaDir.insert(tpaDir.end(), getExtraDirs().begin(), getExtraDirs().end()); + tpaDir.insert(tpaDir.end(), __dllPath->extra_dirs.begin(), __dllPath->extra_dirs.end()); assembliesInDirectory(tpaDir, __tpa); return __tpa; -- 2.7.4 From c844067959c0f4a7e7a39f6ad1a26346cbe98c1b Mon Sep 17 00:00:00 2001 From: Woongsuk Cho Date: Mon, 16 Jul 2018 19:34:59 +0900 Subject: [PATCH 14/16] add log manager to redirect stderr to dlog Change-Id: Ifee7e724f155897dbc92fb27e7f402e5ced6ba54 --- NativeLauncher/CMakeLists.txt | 1 + NativeLauncher/inc/log_manager.h | 24 +++++ NativeLauncher/{util => inc}/path_manager.h | 0 NativeLauncher/inc/utils.h | 5 -- NativeLauncher/launcher/dotnet/dotnet_launcher.cc | 27 +++++- NativeLauncher/util/log_manager.cc | 105 ++++++++++++++++++++++ NativeLauncher/util/utils.cc | 73 --------------- 7 files changed, 153 insertions(+), 82 deletions(-) create mode 100644 NativeLauncher/inc/log_manager.h rename NativeLauncher/{util => inc}/path_manager.h (100%) create mode 100644 NativeLauncher/util/log_manager.cc diff --git a/NativeLauncher/CMakeLists.txt b/NativeLauncher/CMakeLists.txt index b53ec6f..42a59d1 100644 --- a/NativeLauncher/CMakeLists.txt +++ b/NativeLauncher/CMakeLists.txt @@ -69,6 +69,7 @@ SET(${DOTNET_LAUNCHER_UTIL}_SOURCE_FILES util/utils.cc util/plugin_manager.cc util/path_manager.cc + util/log_manager.cc ) ADD_LIBRARY(${DOTNET_LAUNCHER_UTIL} SHARED ${${DOTNET_LAUNCHER_UTIL}_SOURCE_FILES}) SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER_UTIL} PROPERTIES COMPILE_FLAGS "-fPIC") diff --git a/NativeLauncher/inc/log_manager.h b/NativeLauncher/inc/log_manager.h new file mode 100644 index 0000000..bf60651 --- /dev/null +++ b/NativeLauncher/inc/log_manager.h @@ -0,0 +1,24 @@ +/* + * 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 __LOG_MANAGER_H__ +#define __LOG_MANAGER_H__ + +int initializeLogManager(); +int redirectFD(); +int runLoggingThread(); + +#endif /* __LOG_MANAGER_H__ */ diff --git a/NativeLauncher/util/path_manager.h b/NativeLauncher/inc/path_manager.h similarity index 100% rename from NativeLauncher/util/path_manager.h rename to NativeLauncher/inc/path_manager.h diff --git a/NativeLauncher/inc/utils.h b/NativeLauncher/inc/utils.h index e43b63a..d353f92 100644 --- a/NativeLauncher/inc/utils.h +++ b/NativeLauncher/inc/utils.h @@ -102,9 +102,4 @@ typedef std::function FileReader; */ void scanFilesInDir(const std::string& directory, FileReader reader, unsigned int depth); -/** - * @brief start logging thread to bypass stderr and stdout to dlog - * @return return 0 when success, otherwise return negative value. - */ -int runLoggingThread(); #endif /* __UTILS_H__ */ diff --git a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc index 2b2006c..0fb373a 100644 --- a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc +++ b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc @@ -33,6 +33,7 @@ #include "dotnet_launcher.h" #include "plugin_manager.h" #include "path_manager.h" +#include "log_manager.h" #define PLUGIN_PATH "/usr/share/dotnet.tizen/lib/libdotnet_plugin.so" @@ -95,10 +96,6 @@ CoreRuntime::CoreRuntime(const char* mode) : __initialized(false) { _DBG("Constructor called!!"); - - if (runLoggingThread() < 0) { - _ERR("Failed to create logging thread"); - } } CoreRuntime::~CoreRuntime() @@ -142,6 +139,21 @@ int CoreRuntime::initialize(bool standalone) 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); @@ -273,6 +285,13 @@ 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; + } + pluginSetAppInfo(appId, path); int fd2 = open(root, O_DIRECTORY); diff --git a/NativeLauncher/util/log_manager.cc b/NativeLauncher/util/log_manager.cc new file mode 100644 index 0000000..84ae4c0 --- /dev/null +++ b/NativeLauncher/util/log_manager.cc @@ -0,0 +1,105 @@ +/* + * 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 +#include +#include + +#include "log.h" +#include "log_manager.h" + +static int __pfd[2]; +static pthread_t loggingThread; + +static void *stdlog(void*) +{ + ssize_t readSize; + char buf[1024]; + + while ((readSize = read(__pfd[0], buf, sizeof buf - 1)) > 0) { + if (buf[readSize - 1] == '\n') { + --readSize; + } + + buf[readSize] = 0; + + _LOGX("%s", buf); + } + + close(__pfd[0]); + close(__pfd[1]); + + return 0; +} + +int initializeLogManager() +{ + if (setvbuf(stdout, NULL, _IOLBF, 0) < 0) { + _DBG("fail to make stdout line-buffered"); + return -1; + } + + if (setvbuf(stderr, NULL, _IONBF, 0) < 0) { + _DBG("make stderr unbuffered"); + return -1; + } + + /* create the pipe and redirect stdout and stderr */ + if (pipe(__pfd) < 0) { + _DBG("fail to create pipe for logging"); + return -1; + } + + return 0; +} + +int redirectFD() +{ + if (__pfd[1] < 0) { + _DBG("fail to create pipe for logging"); + return -1; + } + // stdout + if (dup2(__pfd[1], 1) == -1) { + _DBG("fail to duplicate fd to stdout"); + return -1; + } + + // stderr + if (dup2(__pfd[1], 2) == -1) { + _DBG("fail to duplicate fd to stderr"); + return-1; + } + + return 0; +} + +int runLoggingThread() +{ + /* spawn the logging thread */ + if (pthread_create(&loggingThread, 0, stdlog, 0) != 0) { + _DBG("fail to create pthread"); + return -1; + } + + if (pthread_detach(loggingThread) != 0) { + _DBG("fail to detach pthread"); + return -1; + } + + return 0; +} + diff --git a/NativeLauncher/util/utils.cc b/NativeLauncher/util/utils.cc index 62f7b9c..fff4cfb 100644 --- a/NativeLauncher/util/utils.cc +++ b/NativeLauncher/util/utils.cc @@ -14,13 +14,11 @@ * limitations under the License. */ -#include #include #include #include #include #include -#include #include #include @@ -33,9 +31,6 @@ #include "utils.h" #include "path_manager.h" -#include "log.h" - -static pthread_t loggingThread; static bool iCompare(const std::string& a, int aOffset, const std::string& b, int bOffset, int length) { @@ -211,71 +206,3 @@ void scanFilesInDir(const std::string& directory, FileReader reader, unsigned in closedir(dir); } -static int __pfd[2]; - -static void *stdlog(void*) -{ - ssize_t readSize; - char buf[1024]; - - while ((readSize = read(__pfd[0], buf, sizeof buf - 1)) > 0) { - if (buf[readSize - 1] == '\n') { - --readSize; - } - - buf[readSize] = 0; - - _LOGX("%s", buf); - } - - close(__pfd[0]); - - return 0; -} - -int runLoggingThread() -{ - if (setvbuf(stdout, NULL, _IOLBF, 0) < 0) { - _DBG("fail to make stdout line-buffered"); - return -1; - } - - if (setvbuf(stderr, NULL, _IONBF, 0) < 0) { - _DBG("make stderr unbuffered"); - return -1; - } - - /* create the pipe and redirect stdout and stderr */ - if (pipe(__pfd) < 0) { - _DBG("fail to create pipe for logging"); - return -1; - } - - // stdout - if (dup2(__pfd[1], 1) == -1) { - _DBG("fail to duplicate fd to stdout"); - return -1; - } - - // stderr - if (dup2(__pfd[1], 2) == -1) { - _DBG("fail to duplicate fd to stderr"); - return -1; - } - - close(__pfd[1]); - - /* spawn the logging thread */ - if (pthread_create(&loggingThread, 0, stdlog, 0) != 0) { - _DBG("fail to create pthread"); - return -1; - } - - if (pthread_detach(loggingThread) != 0) { - _DBG("fail to detach pthread"); - return -1; - } - - return 0; -} - -- 2.7.4 From 5b734248ec9f92af3158489ea2b729bed620d44a Mon Sep 17 00:00:00 2001 From: Woongsuk Cho Date: Tue, 17 Jul 2018 16:13:28 +0900 Subject: [PATCH 15/16] call plugin_initialize before mainloop start Change-Id: Id493273c8e5c9cee92c77d2e8779eae9ed6030b2 --- NativeLauncher/launcher/dotnet/dotnet_launcher.cc | 14 ++++++++------ NativeLauncher/launcher/dotnet/dotnet_launcher.h | 1 - 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc index 0fb373a..676029c 100644 --- a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc +++ b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc @@ -92,10 +92,17 @@ CoreRuntime::CoreRuntime(const char* mode) : __hostHandle(nullptr), __domainId(-1), fd(0), - __mode(mode), __initialized(false) { _DBG("Constructor called!!"); + + // 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() @@ -129,11 +136,6 @@ int CoreRuntime::initialize(bool standalone) putenv(const_cast("UNW_ARM_UNWIND_METHOD=6")); #endif // __arm__ - if (initializePluginManager(__mode) < 0) { - _ERR("Failed to initialize PluginManager"); - return -1; - } - if (initializePathManager(std::string(), std::string(), std::string()) < 0) { _ERR("Failed to initialize PathManager"); return -1; diff --git a/NativeLauncher/launcher/dotnet/dotnet_launcher.h b/NativeLauncher/launcher/dotnet/dotnet_launcher.h index 647640a..6d32a77 100644 --- a/NativeLauncher/launcher/dotnet/dotnet_launcher.h +++ b/NativeLauncher/launcher/dotnet/dotnet_launcher.h @@ -45,7 +45,6 @@ class CoreRuntime void* __hostHandle; unsigned int __domainId; int fd; - const char* __mode; bool __initialized; }; -- 2.7.4 From f58c74485e04f04fbf43edae2c8e039a3e70eef2 Mon Sep 17 00:00:00 2001 From: Woongsuk Cho Date: Tue, 24 Jul 2018 20:07:47 +0900 Subject: [PATCH 16/16] caching tpa list for optimization Change-Id: I7853ff5979afbfdd88bb55910ddd89087ebec1ba --- NativeLauncher/installer-plugin/ni_common.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/NativeLauncher/installer-plugin/ni_common.cc b/NativeLauncher/installer-plugin/ni_common.cc index 8c200ce..f9e81b8 100644 --- a/NativeLauncher/installer-plugin/ni_common.cc +++ b/NativeLauncher/installer-plugin/ni_common.cc @@ -58,6 +58,7 @@ static const char* __CROSSGEN_PATH = __STR(CROSSGEN_PATH); #undef __XSTR static int __interval = 0; +static std::string __tpa; static void waitInterval() { @@ -138,12 +139,11 @@ static void crossgen(const std::string& dllPath, const std::string& appPath, boo return; } } else { - std::string tpa = getTPA(); std::string jitPath = getRuntimeDir() + "/libclrjit.so"; std::vector argv = { __CROSSGEN_PATH, "/nologo", - "/Trusted_Platform_Assemblies", tpa.c_str(), + "/Trusted_Platform_Assemblies", __tpa.c_str(), "/JITPath", jitPath.c_str() }; @@ -272,6 +272,8 @@ int initNICommon(NiCommonOption* option) return -1; } + __tpa = getTPA(); + return 0; } @@ -281,6 +283,8 @@ void finalizeNICommon() finalizePluginManager(); finalizePathManager(); + + __tpa.clear(); } -- 2.7.4