seperate executable to apply User execute label to dotnet-loader
authorWoongsuk Cho <ws77.cho@samsung.com>
Thu, 26 Mar 2020 03:38:20 +0000 (12:38 +0900)
committer이형주/Common Platform Lab(SR)/Staff Engineer/삼성전자 <leee.lee@samsung.com>
Thu, 9 Apr 2020 06:17:18 +0000 (15:17 +0900)
22 files changed:
NativeLauncher/CMakeLists.txt
NativeLauncher/dotnet.loader
NativeLauncher/hydra/hydra_main.cc
NativeLauncher/inc/log.h
NativeLauncher/inc/utils.h
NativeLauncher/launcher/dotnet/dotnet_launcher.cc [deleted file]
NativeLauncher/launcher/dotnet/dotnet_launcher.h [deleted file]
NativeLauncher/launcher/exec/corerun.cc [new file with mode: 0644]
NativeLauncher/launcher/exec/launcher.cc [new file with mode: 0644]
NativeLauncher/launcher/exec/loader.cc [new file with mode: 0644]
NativeLauncher/launcher/injection.cc [deleted file]
NativeLauncher/launcher/injection.h [deleted file]
NativeLauncher/launcher/launcher.cc [deleted file]
NativeLauncher/launcher/launcher.h [deleted file]
NativeLauncher/launcher/lib/dotnet_launcher.cc [new file with mode: 0644]
NativeLauncher/launcher/lib/dotnet_launcher.h [new file with mode: 0644]
NativeLauncher/launcher/lib/injection.cc [new file with mode: 0644]
NativeLauncher/launcher/lib/injection.h [new file with mode: 0644]
NativeLauncher/launcher/main.cc [deleted file]
NativeLauncher/util/utils.cc
dotnet-launcher.manifest
packaging/dotnet-launcher.spec

index d6cefa31992a2a8c94799e2f2c40ef09f796f584..37d1e3f145dcd6240d8ad3a4d72153491dae35cb 100644 (file)
@@ -10,7 +10,7 @@ FOREACH(flag ${${PROJECT_NAME}_CFLAGS})
     SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
 ENDFOREACH(flag)
 
-SET(target_hydra dotnet_hydra_launcher)
+SET(target_hydra dotnet_hydra_loader)
 
 PKG_CHECK_MODULES(${target_hydra} REQUIRED liblaunchpad-hydra)
 
@@ -114,29 +114,62 @@ ADD_LIBRARY(${DOTNET_LAUNCHER_UTIL} SHARED ${${DOTNET_LAUNCHER_UTIL}_SOURCE_FILE
 SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER_UTIL} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_LIB})
 TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER_UTIL} ${${PROJECT_NAME}_LDFLAGS} "-ldl" boost_filesystem boost_system)
 
+SET(DOTNET_LAUNCHER_CORE "dotnet_launcher_core")
+SET(${DOTNET_LAUNCHER_CORE}_SOURCE_FILES
+    launcher/lib/injection.cc
+    launcher/lib/dotnet_launcher.cc
+)
+ADD_LIBRARY(${DOTNET_LAUNCHER_CORE} SHARED ${${DOTNET_LAUNCHER_CORE}_SOURCE_FILES})
+SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER_CORE} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_LIB})
+TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER_CORE} ${${PROJECT_NAME}_LDFLAGS} "-ldl" boost_filesystem boost_system ${DOTNET_LAUNCHER_UTIL})
+
 SET(DOTNET_LAUNCHER "dotnet-launcher")
 SET(${DOTNET_LAUNCHER}_SOURCE_FILES
-    launcher/main.cc
-    launcher/injection.cc
-    launcher/launcher.cc
-    launcher/dotnet/dotnet_launcher.cc
+    launcher/exec/launcher.cc
 )
 ADD_EXECUTABLE(${DOTNET_LAUNCHER} ${${DOTNET_LAUNCHER}_SOURCE_FILES})
 SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_EXE})
-TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl -lpthread" aul ${DOTNET_LAUNCHER_UTIL})
+TARGET_INCLUDE_DIRECTORIES(${DOTNET_LAUNCHER} PRIVATE "launcher/lib")
+TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl -lpthread" aul ${DOTNET_LAUNCHER_UTIL} ${DOTNET_LAUNCHER_CORE})
 
 SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER}
     PROPERTIES SKIP_BUILD_RPATH TRUE
 ) # remove rpath option that is automatically generated by cmake.
 
-SET(DOTNET_HYDRA_LAUNCHER "dotnet-hydra-launcher")
-SET(${DOTNET_HYDRA_LAUNCHER}_SOURCE_FILES
+SET(DOTNET_LOADER "dotnet-loader")
+SET(${DOTNET_LOADER}_SOURCE_FILES
+    launcher/exec/loader.cc
+)
+ADD_EXECUTABLE(${DOTNET_LOADER} ${${DOTNET_LOADER}_SOURCE_FILES})
+SET_TARGET_PROPERTIES(${DOTNET_LOADER} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_EXE})
+TARGET_INCLUDE_DIRECTORIES(${DOTNET_LOADER} PRIVATE "launcher/lib")
+TARGET_LINK_LIBRARIES(${DOTNET_LOADER} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl -lpthread" aul ${DOTNET_LAUNCHER_UTIL} ${DOTNET_LAUNCHER_CORE})
+
+SET_TARGET_PROPERTIES(${DOTNET_LOADER}
+    PROPERTIES SKIP_BUILD_RPATH TRUE
+) # remove rpath option that is automatically generated by cmake.
+
+SET(DOTNET_CORERUN "dotnet")
+SET(${DOTNET_CORERUN}_SOURCE_FILES
+    launcher/exec/corerun.cc
+)
+ADD_EXECUTABLE(${DOTNET_CORERUN} ${${DOTNET_CORERUN}_SOURCE_FILES})
+SET_TARGET_PROPERTIES(${DOTNET_CORERUN} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_EXE})
+TARGET_INCLUDE_DIRECTORIES(${DOTNET_CORERUN} PRIVATE "launcher/lib")
+TARGET_LINK_LIBRARIES(${DOTNET_CORERUN} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl -lpthread" aul ${DOTNET_LAUNCHER_UTIL} ${DOTNET_LAUNCHER_CORE})
+
+SET_TARGET_PROPERTIES(${DOTNET_CORERUN}
+    PROPERTIES SKIP_BUILD_RPATH TRUE
+) # remove rpath option that is automatically generated by cmake.
+
+SET(DOTNET_HYDRA_LOADER "dotnet-hydra-loader")
+SET(${DOTNET_HYDRA_LOADER}_SOURCE_FILES
     hydra/hydra_main.cc
 )
-ADD_EXECUTABLE(${DOTNET_HYDRA_LAUNCHER} ${${DOTNET_HYDRA_LAUNCHER}_SOURCE_FILES})
-TARGET_LINK_LIBRARIES(${DOTNET_HYDRA_LAUNCHER} ${${target_hydra}_LDFLAGS} "-pie -ldl")
-SET_TARGET_PROPERTIES(${DOTNET_HYDRA_LAUNCHER} PROPERTIES COMPILE_FLAGS  ${EXTRA_CFLAGS_HYDRA})
-SET_TARGET_PROPERTIES(${DOTNET_HYDRA_LAUNCHER}
+ADD_EXECUTABLE(${DOTNET_HYDRA_LOADER} ${${DOTNET_HYDRA_LOADER}_SOURCE_FILES})
+TARGET_LINK_LIBRARIES(${DOTNET_HYDRA_LOADER} ${${target_hydra}_LDFLAGS} "-pie -ldl")
+SET_TARGET_PROPERTIES(${DOTNET_HYDRA_LOADER} PROPERTIES COMPILE_FLAGS  ${EXTRA_CFLAGS_HYDRA})
+SET_TARGET_PROPERTIES(${DOTNET_HYDRA_LOADER}
     PROPERTIES SKIP_BUILD_RPATH TRUE
 ) # remove rpath option that is automatically generated by cmake.
 
@@ -200,8 +233,11 @@ TARGET_LINK_LIBRARIES(${PREFER_NUGET_CACHE_PLUGIN} ${${PROJECT_NAME}_LDFLAGS} ${
 CONFIGURE_FILE(dotnet-launcher.pc.in dotnet-launcher.pc @ONLY)
 
 INSTALL(TARGETS ${DOTNET_LAUNCHER_UTIL} DESTINATION ${LIBDIR})
+INSTALL(TARGETS ${DOTNET_LAUNCHER_CORE} DESTINATION ${LIBDIR})
 INSTALL(TARGETS ${DOTNET_LAUNCHER} DESTINATION ${BINDIR})
-INSTALL(TARGETS ${DOTNET_HYDRA_LAUNCHER} DESTINATION ${BINDIR})
+INSTALL(TARGETS ${DOTNET_LOADER} DESTINATION ${BINDIR})
+INSTALL(TARGETS ${DOTNET_CORERUN} DESTINATION ${BINDIR})
+INSTALL(TARGETS ${DOTNET_HYDRA_LOADER} DESTINATION ${BINDIR})
 INSTALL(TARGETS ${TAC_COMMON} DESTINATION ${LIBDIR})
 INSTALL(TARGETS ${NI_COMMON} DESTINATION ${LIBDIR})
 INSTALL(TARGETS ${NITOOL} DESTINATION ${BINDIR})
index fbac5636725e912c051c674c9111fe75eaa96f6d..3422badd7acd0d9efb5548ec741d27832c4dc4f1 100644 (file)
@@ -1,9 +1,9 @@
 [LOADER]
-NAME                   dotnet-launcher
+NAME                   dotnet-loader
 # for candidate mode
-EXE                    /usr/bin/dotnet-launcher
+EXE                    /usr/bin/dotnet-loader
 # for hydra mode
-#EXE                    /usr/bin/dotnet-hydra-launcher
+#EXE                    /usr/bin/dotnet-hydra-loader
 APP_TYPE               dotnet
 DETECTION_METHOD       TIMEOUT|DEMAND
 TIMEOUT                5000
index 8312415a1b44061679dc79cde577907419eea42a..f446e36e671fdda942f024d3b1b45959d43b2563 100644 (file)
@@ -27,7 +27,7 @@
 #include "launcher_env.h"
 
 const char* __coreclr_lib = "/usr/share/dotnet.tizen/netcoreapp/libcoreclr.so";
-const char* __dotnet_launcher = "/usr/bin/dotnet-launcher";
+const char* __dotnet_loader = "/usr/bin/dotnet-loader";
 
 typedef int (*coreclr_preload_assembly_ptr)(const char* assemblyPath);
 typedef int (*launcher_real_main_ptr)(int argc, char *argv[], const char* mode);
@@ -92,7 +92,7 @@ int main(int argc, char** argv)
 
        hydra_callback.fork = [](int argc, char **argv, void* user_data) -> int {
                _INFO("hydra : fork");
-               void* launcher_h = dlopen(__dotnet_launcher, RTLD_NOW | RTLD_GLOBAL);
+               void* launcher_h = dlopen(__dotnet_loader, RTLD_NOW | RTLD_GLOBAL);
                if (launcher_h == nullptr) {
                        _DBG("dlopen failed to open dotnet-launcher");
                        return -1;
index 20f7d2fa4eff989423b4254cf09332093267b17d..bb0ca75420e6a4e0dfbbc160b4e0c0cdeca4039b 100644 (file)
 #ifndef __LOG_H__
 #define __LOG_H__
 
-#ifndef NO_TIZEN
 #include <dlog.h>
 #define LOGX(fmt, arg...) \
        ({ do { \
                dlog_print(DLOG_INFO, LOG_TAG, fmt, ##arg); \
        } while (0); })
 
-#else
-#include <stdio.h>
-#define LOGE(fmt, args...) printf(fmt, ##args)
-#define LOGD(fmt, args...) printf(fmt, ##args)
-#define LOGI(fmt, args...) printf(fmt, ##args)
-#define LOGX(fmt, args...) printf(fmt, ##args)
-#endif
-
 #ifdef  LOG_TAG
 #undef  LOG_TAG
 #endif
 #define _LOGX(fmt, args...) LOGX(fmt "\n", ##args)
 #endif
 
+#ifndef _SOUT
+#define _SOUT(fmt, args...) fprintf(stdout, fmt "\n", ##args)
+#endif
+
+#ifndef _SERR
+#define _SERR(fmt, args...) fprintf(stderr, fmt "\n", ##args)
+#endif
+
 #endif /* __LOG_H__ */
index 3e8c154a96e06b7a57b2baf88ab494ea56fd03e5..b5c11b8c3555f1c99a1f1df75477b85b5ab9f95a 100644 (file)
@@ -216,4 +216,17 @@ bool removeFile(const bf::path& path);
  */
 bool removeAll(const bf::path& path);
 
+/**
+ * @brief change command name of the current process for access via ps command
+ * @param[in] name
+ */
+void setCmdName(const char* name);
+
+/**
+ * @brief get file name from the path
+ * @param[in] file path
+ * @return return file name if exist otherwise null.
+ */
+char* getFileNameFromPath(char* path);
+
 #endif /* __UTILS_H__ */
diff --git a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc
deleted file mode 100644 (file)
index 650d5b7..0000000
+++ /dev/null
@@ -1,640 +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 <dlfcn.h>
-#include <signal.h>
-
-#include <string>
-#include <fstream>
-#include <vector>
-#include <sstream>
-
-#include <locale>
-#include <codecvt>
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <linux/limits.h>
-
-#include <storage.h>
-#include <vconf.h>
-#include <app_common.h>
-
-#include <Ecore.h>
-
-#include "injection.h"
-#include "utils.h"
-#include "log.h"
-#include "launcher.h"
-#include "dotnet_launcher.h"
-#include "plugin_manager.h"
-#include "path_manager.h"
-#include "log_manager.h"
-
-#define __XSTR(x) #x
-#define __STR(x) __XSTR(x)
-static const char* __FRAMEWORK_DIR = __STR(FRAMEWORK_DIR);
-#undef __STR
-#undef __XSTR
-
-namespace tizen {
-namespace runtime {
-namespace dotnetcore {
-
-#if defined (__aarch64__)
-#define ARCHITECTURE_IDENTIFIER "arm64"
-
-#elif defined (__arm__)
-#define ARCHITECTURE_IDENTIFIER "armel"
-
-#elif defined (__x86_64__)
-#define ARCHITECTURE_IDENTIFIER "x64"
-
-#elif defined (__i386__)
-#define ARCHITECTURE_IDENTIFIER "x86"
-
-#else
-#error "Unknown target"
-#endif
-
-static const char* __TIZEN_RID_VERSION_KEY = "db/dotnet/tizen_rid_version";
-
-// The sequence of RID_FALLBACK graphs must be:
-// 1. Tizen + Version + Architecture
-// 2. Tizen + Version
-// 3. OS(tizen, linux, unix) + Architecture
-// 4. OS(tizen, linux, unix)
-// 5. any, base
-static std::string getExtraNativeLibDirs(const std::string& appRoot)
-{
-       std::vector<std::string> RID_FALLBACK_GRAPH;
-       std::vector<std::string> RID_FALLBACK_TIZEN;
-       char* tizen_rid = vconf_get_str(__TIZEN_RID_VERSION_KEY);
-       if (tizen_rid) {
-               std::vector<std::string> version;
-               splitPath(tizen_rid, version);
-               std::reverse(std::begin(version), std::end(version));
-               for (unsigned int i = 0; i < version.size(); i++) {
-                       RID_FALLBACK_TIZEN.push_back(std::string("tizen." + version[i] + "-" + ARCHITECTURE_IDENTIFIER));
-                       RID_FALLBACK_TIZEN.push_back(std::string("tizen." + version[i]));
-               }
-               free(tizen_rid);
-       }
-
-       std::vector<std::string> RID_FALLBACK_OS = {"tizen", "linux", "unix"};
-       for (unsigned int i = 0; i < RID_FALLBACK_OS.size(); i++) {
-               RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i] + "-" +  ARCHITECTURE_IDENTIFIER));
-               RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i]));
-       }
-       RID_FALLBACK_GRAPH.push_back("any");
-       RID_FALLBACK_GRAPH.push_back("base");
-
-       std::string candidate;
-       for (unsigned int i = 0; i < RID_FALLBACK_GRAPH.size(); i++) {
-               if (!candidate.empty()) {
-                       candidate += ":";
-               }
-               candidate += concatPath(appRoot, "bin/runtimes/" + RID_FALLBACK_GRAPH[i] + "/native");
-       }
-
-       candidate = candidate + ":" + concatPath(appRoot, "lib/" ARCHITECTURE_IDENTIFIER);
-       if (!strncmp(ARCHITECTURE_IDENTIFIER, "arm64", 5)) {
-               candidate = candidate + ":" + concatPath(appRoot, "lib/aarch64");
-       } else if (!strncmp(ARCHITECTURE_IDENTIFIER, "armel", 5)) {
-               candidate = candidate + ":" + concatPath(appRoot, "lib/arm");
-       }
-
-       return candidate;
-}
-
-
-static std::vector<std::string> __envList;
-
-static void setEnvFromFile()
-{
-       std::string envList;
-       std::ifstream inFile(ENV_FILE_PATH);
-
-       __envList.clear();
-
-       if (inFile) {
-               _INFO("coreclr_env.list is found");
-
-               std::string token;
-               while (std::getline(inFile, token, '\n')) {
-                       if (!token.empty()) {
-                               __envList.push_back(token);
-                       }
-               }
-
-               for (unsigned int i = 0; i < __envList.size(); i++) {
-                       putenv(const_cast<char *>(__envList[i].c_str()));
-               }
-       } else {
-               _INFO("coreclr_env.list file is not found. skip");
-       }
-}
-
-#define _unused(x) ((void)(x))
-
-struct sigaction sig_abrt_new;
-struct sigaction sig_abrt_old;
-
-static bool checkOnSigabrt = false;
-static bool checkOnTerminate = false;
-
-static void onSigabrt(int signum)
-{
-       // use unused variable to avoid build warning
-       ssize_t ret = write(STDERR_FILENO, "onSigabrt called\n", 17);
-
-       if (checkOnTerminate) {
-               ret = write(STDERR_FILENO, "onSigabrt called while terminate. go to exit\n", 45);
-               _unused(ret);
-               exit(0);
-       }
-
-       if (checkOnSigabrt) {
-               ret = write(STDERR_FILENO, "onSigabrt called again. go to exit\n", 35);
-               _unused(ret);
-               exit(0);
-       }
-
-       checkOnSigabrt = true;
-       if (sigaction(SIGABRT, &sig_abrt_old, NULL) == 0) {
-               if (raise(signum) < 0) {
-                       ret = write(STDERR_FILENO, "Fail to raise SIGABRT\n", 22);
-               }
-       } else {
-               ret = write(STDERR_FILENO, "Fail to set original SIGABRT handler\n", 37);
-       }
-       _unused(ret);
-}
-
-static void registerSigHandler()
-{
-       sig_abrt_new.sa_handler = onSigabrt;
-       if (sigemptyset(&sig_abrt_new.sa_mask) != 0) {
-               _ERR("Fail to sigemptyset");
-       }
-
-       if (sigaction(SIGABRT, &sig_abrt_new, &sig_abrt_old) < 0) {
-               _ERR("Fail to add sig handler");
-       }
-}
-
-static bool storage_cb(int id, storage_type_e type, storage_state_e state, const char *path, void *user_data)
-{
-       int* tmp = (int*)user_data;
-       if (type == STORAGE_TYPE_INTERNAL)
-       {
-               *tmp = id;
-               return false;
-       }
-
-       return true;
-}
-
-static void initEnvForSpecialFolder()
-{
-       int storageId;
-       int error;
-       char *path = NULL;
-
-       error = storage_foreach_device_supported(storage_cb, &storageId);
-       if (error != STORAGE_ERROR_NONE) {
-               return;
-       }
-
-       error = storage_get_directory(storageId, STORAGE_DIRECTORY_IMAGES, &path);
-       if (error == STORAGE_ERROR_NONE && path != NULL) {
-               setenv("XDG_PICTURES_DIR", const_cast<char *>(path), 1);
-               free(path);
-               path = NULL;
-       }
-
-       error = storage_get_directory(storageId, STORAGE_DIRECTORY_MUSIC, &path);
-       if (error == STORAGE_ERROR_NONE && path != NULL) {
-               setenv("XDG_MUSIC_DIR", const_cast<char *>(path), 1);
-               free(path);
-               path = NULL;
-       }
-
-       error = storage_get_directory(storageId, STORAGE_DIRECTORY_VIDEOS, &path);
-       if (error == STORAGE_ERROR_NONE && path != NULL) {
-               setenv("XDG_VIDEOS_DIR", const_cast<char *>(path), 1);
-               free(path);
-               path = NULL;
-       }
-}
-
-// terminate candidate process when language changed
-// icu related data (CultureInfo, etc) should be recreated.
-static void langChangedCB(keynode_t *key, void* data)
-{
-       _INFO("terminiate candidate process to update language.");
-       exit(0);
-}
-
-static void setLang()
-{
-       char* lang = vconf_get_str(VCONFKEY_LANGSET);
-       if (!lang) {
-               _ERR("Fail to get language from vconf");
-               return;
-       }
-
-       // In order to operate ICU (used for globalization) normally, the following
-       // environment variables must be set before using ICU API.
-       // When running Applicaiton, the following environment variables are set by AppFW.
-       // But when preloading the dll in the candidate process, the following environment variables are not set
-       // As a result, CultureInfo is incorrectly generated and malfunctions.
-       // For example, uloc_getDefault() returns en_US_POSIX, CultureInfo is set to invariant mode.
-       setenv("LANG", const_cast<char *>(lang), 1);
-       setenv("LC_MESSAGES", const_cast<char *>(lang), 1);
-       setenv("LC_ALL", const_cast<char *>(lang), 1);
-
-       free(lang);
-}
-
-void CoreRuntime::preloadTypes()
-{
-       const static std::string initDllPath = concatPath(__FRAMEWORK_DIR, "Tizen.Init.dll");
-       if (!isFileExist(initDllPath)) {
-               _ERR("Failed to locate Tizen.Init.dll");
-               return;
-       }
-
-       typedef void (*InitDelegate)();
-       InitDelegate initDelegate;
-
-       int ret = createDelegate(__hostHandle,
-               __domainId,
-               "Tizen.Init",
-               "Tizen.Init.TypeLoader",
-               "PreloadTypes",
-               (void**)&initDelegate);
-
-       if (ret < 0) {
-               _ERR("Failed to create delegate for PreloadTypes (0x%08x)", ret);
-       } else {
-               initDelegate();
-       }
-}
-
-CoreRuntime::CoreRuntime(const char* mode) :
-       initializeClr(nullptr),
-       executeAssembly(nullptr),
-       shutdown(nullptr),
-       createDelegate(nullptr),
-       setEnvironmentVariable(nullptr),
-       __coreclrLib(nullptr),
-       __hostHandle(nullptr),
-       __domainId(-1),
-       __fd(-1),
-       __initialized(false),
-       __isProfileMode(false)
-{
-       _INFO("Constructor called!!");
-
-       // Intiailize ecore first (signal handlers, etc.) before runtime init.
-       ecore_init();
-
-       // set language environment to support ICU
-       setLang();
-
-       char *env = nullptr;
-       env = getenv("CORECLR_ENABLE_PROFILING");
-       if (env != nullptr && !strcmp(env, "1")) {
-               _INFO("profiling mode on");
-               __isProfileMode = true;
-       }
-
-       // plugin initialize should be called before start loader mainloop.
-       // In case of VD plugins, attaching secure zone is done in the plugin_initialize().
-       // When attaching to a secure zone, if there is a created thread, it will failed.
-       // So, plugin initialize should be called before mainloop start.
-       if (initializePluginManager(mode) < 0) {
-               _ERR("Failed to initialize PluginManager");
-       }
-}
-
-CoreRuntime::~CoreRuntime()
-{
-       // workaround : to prevent crash while process terminate on profiling mode,
-       //              kill process immediately.
-       // see https://github.com/dotnet/coreclr/issues/26687
-       if (__isProfileMode) {
-               _INFO("shutdown process immediately.");
-               _exit(0);
-       }
-
-       dispose();
-}
-
-int CoreRuntime::initialize(bool standalone, bool useDlog, const char* corerunRoot)
-{
-       // checkInjection checks dotnet-launcher run mode
-       // At the moment, this mechanism is used only when the Memory Profiler is started.
-       int res = checkInjection();
-       if (res != 0) {
-               _ERR("Failed to initnialize Memory Profiler");
-               return -1;
-       }
-#define __XSTR(x) #x
-#define __STR(x) __XSTR(x)
-
-#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.
-       // Therefore let's disable stack unwinding using DWARF information
-       // See https://github.com/dotnet/coreclr/issues/6698
-       //
-       // libunwind use following methods to unwind stack frame.
-       // UNW_ARM_METHOD_ALL          0xFF
-       // UNW_ARM_METHOD_DWARF        0x01
-       // UNW_ARM_METHOD_FRAME        0x02
-       // UNW_ARM_METHOD_EXIDX        0x04
-       putenv(const_cast<char *>("UNW_ARM_UNWIND_METHOD=6"));
-#endif // __arm__
-
-       // Disable debug pipes and semaphores creation in case of non-standlone mode
-       if (!standalone)
-               putenv(const_cast<char *>("COMPlus_EnableDiagnostics=0"));
-
-       // Write Debug.WriteLine to stderr
-       putenv(const_cast<char *>("COMPlus_DebugWriteToStdErr=1"));
-
-#ifdef USE_DEFAULT_BASE_ADDR
-       putenv(const_cast<char *>("COMPlus_UseDefaultBaseAddr=1"));
-#endif // USE_DEFAULT_BASE_ADDR
-
-       // read string from external file and set them to environment value.
-       setEnvFromFile();
-
-       if (initializePathManager(std::string(), std::string(), std::string()) < 0) {
-               _ERR("Failed to initialize PathManager");
-               return -1;
-       }
-
-       if (useDlog && !pluginHasLogControl()) {
-               if (initializeLogManager() < 0) {
-                       _ERR("Failed to initnialize LogManager");
-                       return -1;
-               }
-       }
-
-       std::string libCoreclr(concatPath(getRuntimeDir(), "libcoreclr.so"));
-
-       __coreclrLib = dlopen(libCoreclr.c_str(), RTLD_NOW | RTLD_LOCAL);
-       if (__coreclrLib == nullptr) {
-               char *err = dlerror();
-               _ERR("dlopen failed to open libcoreclr.so with error %s", err);
-               if (access(libCoreclr.c_str(), R_OK) == -1)
-                       _ERR("access '%s': %s\n", libCoreclr.c_str(), strerror(errno));
-               return -1;
-       }
-
-#define CORELIB_RETURN_IF_NOSYM(type, variable, name) \
-       do { \
-               variable = (type)dlsym(__coreclrLib, name); \
-               if (variable == nullptr) { \
-                       _ERR(name " is not found in the libcoreclr.so"); \
-                       return -1; \
-               } \
-       } while (0)
-
-       CORELIB_RETURN_IF_NOSYM(coreclr_initialize_ptr, initializeClr, "coreclr_initialize");
-       CORELIB_RETURN_IF_NOSYM(coreclr_execute_assembly_ptr, executeAssembly, "coreclr_execute_assembly");
-       CORELIB_RETURN_IF_NOSYM(coreclr_shutdown_ptr, shutdown, "coreclr_shutdown");
-       CORELIB_RETURN_IF_NOSYM(coreclr_create_delegate_ptr, createDelegate, "coreclr_create_delegate");
-
-#undef CORELIB_RETURN_IF_NOSYM
-
-       _INFO("libcoreclr dlopen and dlsym success");
-
-       if (!standalone) {
-               pluginPreload();
-
-               // terminate candidate process if language is changed.
-               // CurrentCulture created for preloaded dlls should be updated.
-               vconf_notify_key_changed(VCONFKEY_LANGSET, langChangedCB, NULL);
-       }
-
-       // Set environment for System.Environment.SpecialFolder
-       // Below function creates dbus connection by callging storage API.
-       // If dbus connection is created bofere fork(), forked process cannot use dbus.
-       // To avoid gdbus blocking issue, below function should be called after fork()
-       initEnvForSpecialFolder();
-
-       std::string tpa = getTPA();
-       std::string runtimeDir = getRuntimeDir();
-       std::string appName = std::string("dotnet-launcher-") + std::to_string(getpid());
-       std::string probePath;
-       std::string NIprobePath;
-       std::string nativeLibPath;
-
-       if (corerunRoot) {
-               probePath = corerunRoot;
-               NIprobePath = corerunRoot;
-               nativeLibPath = corerunRoot;
-       } else  {
-               __fd = open("/proc/self", O_DIRECTORY);
-               if (__fd < 0) {
-                       _ERR("Failed to open /proc/self");
-                       return -1;
-               }
-               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 appTac = concatPath(appBin, TAC_SYMLINK_SUB_DIR);
-               probePath = appRoot + ":" + appBin + ":" + appLib + ":" + appTac;
-               NIprobePath = concatPath(appBin, APP_NI_SUB_DIR) + ":" + concatPath(appLib, APP_NI_SUB_DIR) + ":" + appTac;
-               nativeLibPath = getExtraNativeLibDirs(appRoot) + ":" + appBin + ":" + appLib + ":" + __nativeLibDirectory + ":" + runtimeDir;
-       }
-
-       if (!initializeCoreClr(appName.c_str(), probePath.c_str(), NIprobePath.c_str(), nativeLibPath.c_str(), tpa.c_str())) {
-               _ERR("Failed to initialize coreclr");
-               return -1;
-       }
-
-       int st = createDelegate(__hostHandle, __domainId, "Dotnet.Launcher", "Dotnet.Launcher.Environment", "SetEnvironmentVariable", (void**)&setEnvironmentVariable);
-       if (st < 0 || setEnvironmentVariable == nullptr) {
-               _ERR("Create delegate for Dotnet.Launcher.dll -> Dotnet.Launcher.Environment -> SetEnvironmentVariable failed (0x%08x)", st);
-               return -1;
-       }
-
-       __initialized = true;
-
-       if (!standalone) {
-               preloadTypes();         // Preload common managed code
-       }
-
-       _INFO("CoreRuntime initialize success");
-
-       return 0;
-}
-
-bool CoreRuntime::initializeCoreClr(const char* appId,
-                                                                        const char* assemblyProbePaths,
-                                                                        const char* NIProbePaths,
-                                                                        const char* pinvokeProbePaths,
-                                                                        const char* tpaList)
-{
-       const char *propertyKeys[] = {
-               "TRUSTED_PLATFORM_ASSEMBLIES",
-               "APP_PATHS",
-               "APP_NI_PATHS",
-               "NATIVE_DLL_SEARCH_DIRECTORIES",
-               "AppDomainCompatSwitch"
-       };
-
-       const char *propertyValues[] = {
-               tpaList,
-               assemblyProbePaths,
-               NIProbePaths,
-               pinvokeProbePaths,
-               "UseLatestBehaviorWhenTFMNotSpecified"
-       };
-
-       std::string selfPath = readSelfPath();
-
-       int st = initializeClr(selfPath.c_str(),
-                                                       appId,
-                                                       sizeof(propertyKeys) / sizeof(propertyKeys[0]),
-                                                       propertyKeys,
-                                                       propertyValues,
-                                                       &__hostHandle,
-                                                       &__domainId);
-
-       if (st < 0) {
-               _ERR("initialize core clr fail! (0x%08x)", st);
-               return false;
-       }
-
-       pluginSetCoreclrInfo(__hostHandle, __domainId, createDelegate);
-
-       _INFO("Initialize core clr success");
-       return true;
-}
-
-void CoreRuntime::dispose()
-{
-       // call plugin finalize function to notify finalize to plugin
-       // dlclose shoud be done after coreclr shutdown to avoid breaking signal chain
-       pluginFinalize();
-
-       // ignore the signal generated by an exception that occurred during shutdown
-       checkOnTerminate = true;
-
-       if (__hostHandle != nullptr) {
-               int st = shutdown(__hostHandle, __domainId);
-               if (st < 0)
-                       _ERR("shutdown core clr fail! (0x%08x)", st);
-               __hostHandle = nullptr;
-       }
-
-       if (__coreclrLib != nullptr) {
-               if (dlclose(__coreclrLib) != 0) {
-                       _ERR("libcoreclr.so close failed");
-               }
-
-               __coreclrLib = nullptr;
-       }
-
-       finalizePluginManager();
-       finalizePathManager();
-
-       __envList.clear();
-
-       _INFO("Dotnet runtime disposed");
-}
-
-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 -1;
-       }
-
-       if (!isFileExist(path)) {
-               _ERR("File not exist : %s", path);
-               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 LogManager is not initialized, below redirectFD will return 0;
-       if (redirectFD() < 0) {
-               _ERR("Failed to redirect FD");
-               return -1;
-       }
-
-       // VD has their own signal handler.
-       if (!pluginHasLogControl()) {
-               registerSigHandler();
-       }
-
-       pluginSetAppInfo(appId, path);
-
-       // override root path for application launch mode (candidate / standalone mode)
-       if (__fd >= 0) {
-               int fd2 = open(root, O_DIRECTORY);
-               dup3(fd2, __fd, O_CLOEXEC);
-               if (fd2 >= 0)
-                       close(fd2);
-       }
-
-       // set application data path to coreclr environment.
-       // application data path can be changed by owner. So, we have to set data path just before launching.
-       char* localDataPath = app_get_data_path();
-       if (localDataPath != nullptr) {
-               setEnvironmentVariable("XDG_DATA_HOME", localDataPath);
-               free(localDataPath);
-       }
-
-       vconf_ignore_key_changed(VCONFKEY_LANGSET, langChangedCB);
-
-       pluginBeforeExecute();
-
-       _INFO("execute assembly : %s", path);
-
-       unsigned int ret = 0;
-       int st = executeAssembly(__hostHandle, __domainId, argc, (const char**)argv, path, &ret);
-       if (st < 0)
-               _ERR("Failed to Execute Assembly %s (0x%08x)", path, st);
-       return ret;
-}
-
-}  // namespace dotnetcore
-}  // namespace runtime
-}  // namespace tizen
diff --git a/NativeLauncher/launcher/dotnet/dotnet_launcher.h b/NativeLauncher/launcher/dotnet/dotnet_launcher.h
deleted file mode 100644 (file)
index f5cedc9..0000000
+++ /dev/null
@@ -1,60 +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 __DOTNET_LAUNCHER_H__
-#define __DOTNET_LAUNCHER_H__
-
-#include "launcher.h"
-#include "coreclr_host.h"
-#include "plugin_manager.h"
-
-namespace tizen {
-namespace runtime {
-namespace dotnetcore {
-
-class CoreRuntime
-{
-       public:
-               CoreRuntime(const char* mode);
-               ~CoreRuntime();
-               int initialize(bool standalone, bool useDlog, const char* corerunRoot);
-               void dispose();
-               int launch(const char* appId, const char* root, const char* path, int argc, char* argv[]);
-
-       private:
-
-               bool initializeCoreClr(const char* appId, const char* assemblyProbePaths, const char* NIProbePaths, const char* pinvokeProbePaths, const char* tpaList);
-               void preloadTypes();
-               coreclr_initialize_ptr initializeClr;
-               coreclr_execute_assembly_ptr executeAssembly;
-               coreclr_shutdown_ptr shutdown;
-               coreclr_create_delegate_ptr createDelegate;
-               set_environment_variable_ptr setEnvironmentVariable;
-               std::string __nativeLibDirectory;
-               void* __coreclrLib;
-               void* __hostHandle;
-               unsigned int __domainId;
-               int __fd;
-               bool __initialized;
-               bool __isProfileMode;
-
-};
-
-}  // dotnetcore
-}  // namespace runtime
-}  // namespace tizen
-
-#endif /* __DOTNET_LAUNCHER_H__ */
diff --git a/NativeLauncher/launcher/exec/corerun.cc b/NativeLauncher/launcher/exec/corerun.cc
new file mode 100644 (file)
index 0000000..2a78bae
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dotnet_launcher.h"
+#include "utils.h"
+#include "log.h"
+
+using tizen::runtime::dotnetcore::CoreRuntime;
+
+int main(int argc, char *argv[])
+{
+       _INFO("##### Run in corerun mode #####");
+
+       if (argc < 2) {
+               _SOUT("No parameter");
+               return -1;
+       }
+
+       if (!isManagedAssembly(argv[1]) && !isNativeImage(argv[1])) {
+               _SOUT("first parameter should be assembly file");
+               return -1;
+       }
+
+       // remove executable and assembly path form the arguments and pass that to managed code
+       int vargc = argc - 2;
+       std::vector<char*> vargs;
+       for (int i = 0; i < vargc; i++) {
+               vargs.push_back(argv[2 + i]);
+       }
+
+       // set command name to assembly file
+       char* fileName = getFileNameFromPath(argv[1]);
+       setCmdName(fileName);
+       
+       CoreRuntime* runtime = new CoreRuntime("corerun");
+
+       // get absolute path of input dll file
+       std::string absoluteDllPath = absolutePath(argv[1]);
+
+       if (runtime->initialize(LaunchMode::corerun, false, absoluteDllPath.c_str()) != 0) {
+               _SOUT("Failed to initialize");
+               return -1;
+       }
+
+       // launch application
+       if (runtime->launch(fileName, baseName(absoluteDllPath).c_str(), absoluteDllPath.c_str(), vargc, &vargs[0])) {
+               _SOUT("Failed to launch");
+               return -1;
+       }
+
+       return 0;
+}
+
diff --git a/NativeLauncher/launcher/exec/launcher.cc b/NativeLauncher/launcher/exec/launcher.cc
new file mode 100644 (file)
index 0000000..5a4ff57
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dotnet_launcher.h"
+#include "utils.h"
+#include "log.h"
+
+#include <cstdio>
+#include <vector>
+#include <memory>
+
+#include <aul.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <sys/prctl.h>
+
+using tizen::runtime::dotnetcore::CoreRuntime;
+
+// By the specification, application id must be shorter than 50 characters.
+// Current length of argv[0] is 25 with a space. ("/usr/bin/dotnet-launcher ")
+// To be able to change argv[0] when standalone mode padding for executable path is added.
+#define APPID_MAX_LENGTH       (25 + 105)
+#define PRC_NAME_LENGTH                16
+
+static std::string StandaloneOption("--standalone");
+static std::string PaddingOption("--PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE");
+
+int main(int argc, char *argv[])
+{
+       _INFO("##### Run in standalone mode #####");
+       
+       char* standalonePath = nullptr;
+       bool paddingExist = false;
+       const char* appRootPath = NULL;
+       char appId[APPID_MAX_LENGTH] = {0,};
+
+       std::vector<char*> vargs;
+
+       // start index 1 to avoid passing executable name "dotnet-launcher" as a parameter
+       for (int i = 1; i < argc; i++) {
+               if (StandaloneOption.compare(argv[i]) == 0) {
+                       if (i > argc - 1) {
+                               _ERR("Assembly path must be after \"--standalone\" option");
+                               return -1;
+                       }
+                       i++;
+                       standalonePath = argv[i];
+               } else if (PaddingOption.compare(argv[i]) == 0) {
+                       paddingExist = true;
+               } else {
+                       vargs.push_back(argv[i]);
+               }
+       }
+
+       CoreRuntime* runtime = new CoreRuntime("standalone");
+
+       // get app ID and app root path
+       if (AUL_R_OK == aul_app_get_appid_bypid(getpid(), appId, sizeof(appId))) {
+               _INFO("AUL_APPID : %s", appId);
+               // aul_get_app_root_path returns const char*, so there is no need to free after use.
+               appRootPath = aul_get_app_root_path();
+               if (appRootPath == nullptr) {
+                       _ERR("Fail to get application root path");
+                       return -1;
+               }
+       } else {
+               _ERR("Fail to get app_id");
+               return -1;
+       }
+
+       // set command name to assembly file
+       setCmdName(getFileNameFromPath(standalonePath));
+
+       // change cmdline from dotnet-launcher to executable path
+       int cmdlineSize = paddingExist ? APPID_MAX_LENGTH : APPID_MAX_LENGTH - PaddingOption.length();
+       memset(argv[0], '\0', cmdlineSize);
+       snprintf(argv[0], cmdlineSize - 1, "%s", standalonePath);
+
+       // initialize CoreRuntime (standalone mode enable, dlog redirection enable, root path NULL)
+       if (runtime->initialize(LaunchMode::launcher, true, appRootPath) != 0) {
+               _ERR("Failed to initialize");
+               return -1;
+       }
+
+       // launch application
+       if (runtime->launch(appId, appRootPath, standalonePath, vargs.size(), &vargs[0])) {
+               _ERR("Failed to launch");
+               return -1;
+       }
+
+       return 0;
+}
+
diff --git a/NativeLauncher/launcher/exec/loader.cc b/NativeLauncher/launcher/exec/loader.cc
new file mode 100644 (file)
index 0000000..c090fd9
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dotnet_launcher.h"
+#include "utils.h"
+#include "log.h"
+
+#include <cstdio>
+#include <vector>
+#include <memory>
+
+#include <Ecore.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/prctl.h>
+
+#include <launchpad.h>
+#include <aul.h>
+
+using tizen::runtime::dotnetcore::CoreRuntime;
+
+static Ecore_Fd_Handler *__fd_handler;
+static loader_receiver_cb __receiver;
+
+// To precreate window(EFL/DALI), argc and argv should be passed.
+// But, create callback of loader doesnot pass that to parameter.
+// So, store argc and argv and use that to precreation.
+// If window precreation code moves to managed, removed below code.
+static int __argc;
+static char **__argv;
+
+typedef struct AppInfo {
+       std::string root;
+       std::string app_path;
+       std::string appid;
+       std::string pkgid;
+} AppInfo;
+static AppInfo __appInfo;
+
+
+//################## Code for running event loop for loader ####################
+
+static Eina_Bool __process_fd_handler(void *data, Ecore_Fd_Handler *handler)
+{
+       int fd;
+
+       fd = ecore_main_fd_handler_fd_get(handler);
+       if (fd == -1) {
+               _ERR("[candidate] ECORE_FD_GET");
+               exit(-1);
+       }
+
+       if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ)) {
+               if (__receiver)
+                       __receiver(fd);
+       } else if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR)) {
+               _ERR("[candidate] ECORE_FD_ERROR");
+               close(fd);
+               exit(-1);
+       }
+
+       return ECORE_CALLBACK_CANCEL;
+}
+
+static void __adapter_loop_begin(void *user_data)
+{
+       ecore_main_loop_begin();
+}
+
+static void __adapter_loop_quit(void *user_data)
+{
+       ecore_main_loop_quit();
+}
+
+static void __adapter_add_fd(void *user_data, int fd,
+               loader_receiver_cb receiver)
+{
+       __fd_handler = ecore_main_fd_handler_add(fd,
+                       static_cast<Ecore_Fd_Handler_Flags>(ECORE_FD_READ | ECORE_FD_ERROR),
+                       __process_fd_handler, NULL, NULL, NULL);
+       
+       if (__fd_handler == NULL) {
+               _ERR("fd_handler is NULL");
+               close(fd);
+               exit(-1);
+       }
+
+       __receiver = receiver;
+}
+
+static void __adapter_remove_fd(void *user_data, int fd)
+{
+       if (__fd_handler) {
+               ecore_main_fd_handler_del(__fd_handler);
+               __fd_handler = NULL;
+               __receiver = NULL;
+       }
+}
+
+//################## Code for managing loader life-cycle #######################
+
+static void __loader_create_cb(bundle *extra, int type, void *user_data)
+{
+       CoreRuntime* runtime = (CoreRuntime*)user_data;
+
+       {
+               // do native window precreation here
+       }
+
+       // initialize CoreRuntime (launchmode, dlog redirection enable, root path NULL)
+       if (runtime->initialize(LaunchMode::loader, true, NULL) != 0) {
+               _ERR("Failed to initialized");
+       } else {
+               _INFO("Success to initialized");
+       }       
+}
+
+static int __loader_launch_cb(int argc, char **argv, const char *app_path,
+               const char *appid, const char *pkgid, const char *pkg_type,
+               void *user_data)
+{
+       const char* root_path = aul_get_app_root_path();
+       if (root_path != NULL) {
+               __appInfo.root = root_path;
+       }
+
+       __appInfo.app_path = app_path;
+       __appInfo.appid = appid;
+       __appInfo.pkgid = pkgid;
+
+       return 0;
+}
+       
+static int __loader_terminate_cb(int argc, char **argv, void *user_data)
+{
+       CoreRuntime* runtime = (CoreRuntime*)user_data;
+
+       _INFO("launch request with app path : %s", __appInfo.app_path.c_str());
+
+       // The launchpad pass the name of exe file to the first argument.
+       // For the C# spec, we have to skip this first argument.
+       if (runtime->launch(__appInfo.appid.c_str(), __appInfo.root.c_str(), 
+                                               __appInfo.app_path.c_str(), argc - 1, argv + 1)) {
+               _ERR("Failed to launch");
+       }
+
+       return 0;
+}
+
+//################## Main Code #################################################
+
+extern "C" int realMain(int argc, char *argv[], const char* mode)
+{
+       _INFO("##### Run in candidate mode #####");
+       
+       CoreRuntime* runtime = new CoreRuntime(mode);
+
+       // change cmdline from dotnet-hydra-loader to dotnet-loader
+       if (strcmp(argv[0], "/usr/bin/dotnet-hydra-loader") == 0) {
+               memset(argv[0], '\0', strlen("/usr/bin/dotnet-hydra-loader"));
+               snprintf(argv[0], strlen("/usr/bin/dotnet-loader") + 1,
+                                               "/usr/bin/dotnet-loader");
+       }
+
+       setCmdName("dotnet-loader");
+
+       loader_lifecycle_callback_s callbacks = {
+               .create = __loader_create_cb,
+               .launch = __loader_launch_cb,
+               .terminate = __loader_terminate_cb
+       };
+
+       loader_adapter_s adapter = {
+               .loop_begin = __adapter_loop_begin,
+               .loop_quit = __adapter_loop_quit,
+               .add_fd = __adapter_add_fd,
+               .remove_fd = __adapter_remove_fd
+       };
+       
+       return launchpad_loader_main(argc, argv, &callbacks, &adapter, runtime);
+}
+
+int main(int argc, char *argv[])
+{
+       __argc = argc;
+       __argv = argv;
+
+       return realMain(argc, argv, "candidate");
+}
+
diff --git a/NativeLauncher/launcher/injection.cc b/NativeLauncher/launcher/injection.cc
deleted file mode 100644 (file)
index 819af59..0000000
+++ /dev/null
@@ -1,79 +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 "log.h"
-
-#include <cstdlib>
-#include <cstring>
-
-#include <dlfcn.h>
-
-#define HT_PATH "/home/owner/share/tmp/sdk_tools/heaptrack/"
-#define HT_LIB_PATH HT_PATH "libprofiler.so"
-#define HT_INJECTION_LIB_PATH HT_PATH "libheaptrack_inject.so"
-
-static int injectLibrary(const char path[])
-{
-       typedef int inject_func();
-
-       int res = -1;
-       void *lib = nullptr;
-       inject_func *inject = nullptr;
-       const char *inject_sym = "dotnet_launcher_inject";
-
-       _INFO("Inject %s library", path);
-
-       // Current implementation of heaptrack CLR profiler requires RTLD_GLOBAL
-       lib = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
-       if (lib == nullptr) {
-               _ERR("%s", dlerror());
-               return res;
-       }
-
-       inject = reinterpret_cast<inject_func*>(dlsym(lib, inject_sym));
-       if (inject == nullptr) {
-               _ERR("%s is not found in the %s", inject_sym, path);
-               return res;
-       }
-
-       res = inject();
-       return res;
-}
-
-int checkInjection()
-{
-       char *env = nullptr;
-
-       env = getenv("CORECLR_PROFILER_PATH");
-       if (env == nullptr) {
-               return 0;
-       }
-
-       // At the moment, this mechanism is used only when the Memory Profiler is started.
-       if (strcmp(env, HT_LIB_PATH) != 0) {
-               return 0;
-       }
-
-       _INFO("##### Perform injection #########");
-
-       if (injectLibrary(HT_INJECTION_LIB_PATH) != 0) {
-               _INFO("##### Injection failed #########");
-               return -1;
-       }
-
-       _INFO("##### Injection finished #########");
-       return 0;
-}
diff --git a/NativeLauncher/launcher/injection.h b/NativeLauncher/launcher/injection.h
deleted file mode 100644 (file)
index 6bcf111..0000000
+++ /dev/null
@@ -1,22 +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 __INJETION_INTERFACE_H__
-#define __INJETION_INTERFACE_H__
-
-int checkInjection();
-
-#endif // __INJETION_INTERFACE_H__
diff --git a/NativeLauncher/launcher/launcher.cc b/NativeLauncher/launcher/launcher.cc
deleted file mode 100644 (file)
index 7af7576..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "launcher.h"
-#include "log.h"
-
-#include <launchpad.h>
-#include <aul.h>
-
-#include <Ecore.h>
-#include <bundle_internal.h>
-
-#include <map>
-#include <vector>
-#include <functional>
-
-#include <unistd.h>
-#include <dlfcn.h>
-
-
-namespace tizen {
-namespace runtime {
-
-struct FdHandler {
-       Ecore_Fd_Handler *handler;
-       loader_receiver_cb receiver;
-};
-
-static int __argc;
-static char **__argv;
-
-class LaunchpadAdapterImpl : public LaunchpadAdapter
-{
-       public:
-               LaunchpadAdapterImpl() :
-                       callbacks(),
-                       adapter(),
-                       __isLaunched(false)
-               { }
-               int loaderMain(int argc, char* argv[]) override;
-
-               std::map<int, FdHandler> handlers;
-
-       private:
-               AppInfo appInfo;
-               loader_lifecycle_callback_s callbacks;
-               loader_adapter_s adapter;
-               bool __isLaunched;
-               std::string __launchPath;
-};
-
-LaunchpadAdapterImpl LaunchpadImpl;
-LaunchpadAdapter& Launchpad = LaunchpadImpl;
-
-#define WITH_SELF(data) \
-       LaunchpadAdapterImpl* self = static_cast<LaunchpadAdapterImpl*>(data); \
-       if (self == nullptr) \
-               _ERR("No LaunchpadImplData"); \
-       else
-
-static Eina_Bool fdHandler(void *data, Ecore_Fd_Handler* handler)
-{
-       WITH_SELF(data) {
-               int fd = ecore_main_fd_handler_fd_get(handler);
-               if (fd == -1) {
-                       _ERR("Failed to get the Ecore FD");
-                       exit(-1);
-               }
-
-               if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ)) {
-                       if (self->handlers.find(fd) != self->handlers.end())
-                               self->handlers[fd].receiver(fd);
-               } else if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR)) {
-                       _ERR("Ecore FD Handler Have Error");
-                       close(fd);
-                       exit(-1);
-               }
-       }
-
-       return ECORE_CALLBACK_CANCEL;
-}
-
-static void fdAdd(void *data, int fd, loader_receiver_cb receiver)
-{
-       Ecore_Fd_Handler* handler = ecore_main_fd_handler_add(fd,
-                       static_cast<Ecore_Fd_Handler_Flags>(ECORE_FD_READ | ECORE_FD_ERROR),
-                       fdHandler, data, nullptr, nullptr);
-       if (handler == nullptr) {
-               _ERR("Failed to add a FD handler to ecore main loop");
-               close(fd);
-               exit(-1);
-       } WITH_SELF(data) {
-               self->handlers[fd] = {handler, receiver};
-       }
-}
-
-static void fdRemove(void *data, int fd)
-{
-       WITH_SELF(data) {
-               if (self->handlers.find(fd) != self->handlers.end()) {
-                       Ecore_Fd_Handler* handler = self->handlers[fd].handler;
-                       ecore_main_fd_handler_del(handler);
-                       self->handlers.erase(fd);
-               }
-       }
-}
-
-// To run dotnet-launcher on the headless device, remove build dependency from EFL.
-#define ELEMENTARY_PATH "/usr/lib/libelementary.so.1"
-static void* __win;
-typedef int (*elm_init_ptr)(int argc, char **argv);
-typedef void (*elm_config_accel_preference_set_ptr)(const char *pref);
-typedef void* (*elm_win_add_ptr)(void* parent, const char* name, int type);
-typedef void (*elm_win_precreated_object_set_ptr)(void* win);
-
-static void preCreateWindow()
-{
-       struct stat sb;
-       if (stat(ELEMENTARY_PATH, &sb) != 0) {
-               _ERR("[candidate] libelementary is not exist. skip precreation");
-               return;
-       }
-
-       int elmInitCnt = 0;
-       void* handle = nullptr;
-       elm_init_ptr elm_init = nullptr;
-       elm_config_accel_preference_set_ptr elm_config_accel_preference_set = nullptr;
-       elm_win_add_ptr elm_win_add = nullptr;
-       elm_win_precreated_object_set_ptr elm_win_precreated_object_set = nullptr;
-
-       handle = dlopen(ELEMENTARY_PATH, RTLD_NOW | RTLD_GLOBAL);
-       if (handle) {
-               elm_init = (elm_init_ptr)dlsym(handle, "elm_init");
-               if (elm_init) {
-                       elmInitCnt = elm_init(__argc, __argv);
-
-                       if (!elmInitCnt) {
-                               _ERR("[candidate] elm_init() failed");
-                               return;
-                       }
-               }
-
-               elm_config_accel_preference_set = (elm_config_accel_preference_set_ptr)dlsym(handle, "elm_config_accel_preference_set");
-               if (elm_config_accel_preference_set) {
-                       elm_config_accel_preference_set("hw");
-               }
-
-               elm_win_add = (elm_win_add_ptr)dlsym(handle, "elm_win_add");
-               if (elm_win_add) {
-                       // enum value of "ELM_WIN_BASIC" is 0
-                       __win = elm_win_add(NULL, "package_name", 0);
-                       if (__win == NULL) {
-                               _ERR("[candidate] elm_win_add() failed");
-                               return;
-                       }
-               }
-
-               elm_win_precreated_object_set = (elm_win_precreated_object_set_ptr)dlsym(handle, "elm_win_precreated_object_set");
-               if (elm_win_precreated_object_set) {
-                       elm_win_precreated_object_set(__win);
-               }
-               _INFO("elm window precreation is done");
-       }
-}
-
-int LaunchpadAdapterImpl::loaderMain(int argc, char* argv[])
-{
-       __argc = argc;
-       __argv = argv;
-       callbacks.create = [](bundle *extra, int type, void *userData) {
-               preCreateWindow();
-               WITH_SELF(userData) {
-                       if (self->onCreate != nullptr)
-                               self->onCreate();
-               }
-       };
-       callbacks.launch = [](int argc, char** argv, const char* appPath,
-                                               const char* appId, const char* pkgId,
-                                               const char* pkgType, void* userData) -> int {
-               WITH_SELF(userData) {
-                       const char* appRootPath = aul_get_app_root_path();
-                       if (appRootPath != nullptr) {
-                               self->appInfo.root = std::string(appRootPath);
-                       }
-                       self->appInfo.path = appPath;
-                       self->appInfo.id = appId;
-                       self->appInfo.pkg = pkgId;
-                       self->appInfo.type = pkgType;
-                       if (self->onLaunch != nullptr)
-                               self->onLaunch(self->appInfo, argc, argv);
-               }
-
-               return 0;
-       };
-       callbacks.terminate = [](int argc, char **argv, void* userData) -> int {
-               WITH_SELF(userData) {
-                       if (self->onTerminate != nullptr)
-                               self->onTerminate(self->appInfo, argc, argv);
-               }
-               return 0;
-       };
-
-       adapter.loop_begin = [](void *data) {
-               ecore_main_loop_begin();
-       };
-
-       adapter.loop_quit = [](void *data) {
-               ecore_main_loop_quit();
-       };
-       adapter.add_fd = fdAdd;
-       adapter.remove_fd = fdRemove;
-
-       _INFO("launchpad_loader_main is start");
-       int r = launchpad_loader_main(argc, argv, &(this->callbacks), &(this->adapter), this);
-       _INFO("launchpad_loader_main is finished with [%d]", r);
-
-       return r;
-}
-
-#undef WITH_SELF
-
-}  // namespace runtime
-}  // namespace tizen
diff --git a/NativeLauncher/launcher/launcher.h b/NativeLauncher/launcher/launcher.h
deleted file mode 100644 (file)
index e48f318..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __LAUNCHER_INTERFACE_H__
-#define __LAUNCHER_INTERFACE_H__
-
-#include <string>
-#include <functional>
-
-namespace tizen {
-namespace runtime {
-
-struct AppInfo {
-       std::string root;
-       std::string path;
-       std::string id;
-       std::string pkg;
-       std::string type;
-};
-
-class LaunchpadAdapter
-{
-       public:
-               virtual int loaderMain(int argc, char* argv[]) = 0;
-               std::function<void()> onCreate = nullptr;
-               std::function<void(const AppInfo&, int, char**)> onLaunch = nullptr;
-               std::function<void(const AppInfo&, int, char**)> onTerminate = nullptr;
-};
-
-extern LaunchpadAdapter& Launchpad;
-
-}  // namespace runtime
-}  // namespace tizen
-
-#endif /* __LAUNCHER_INTERFACE_H__ */
diff --git a/NativeLauncher/launcher/lib/dotnet_launcher.cc b/NativeLauncher/launcher/lib/dotnet_launcher.cc
new file mode 100644 (file)
index 0000000..c900ef2
--- /dev/null
@@ -0,0 +1,639 @@
+/*
+ * 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 <dlfcn.h>
+#include <signal.h>
+
+#include <string>
+#include <fstream>
+#include <vector>
+#include <sstream>
+
+#include <locale>
+#include <codecvt>
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <linux/limits.h>
+
+#include <storage.h>
+#include <vconf.h>
+#include <app_common.h>
+
+#include <Ecore.h>
+
+#include "injection.h"
+#include "utils.h"
+#include "log.h"
+#include "dotnet_launcher.h"
+#include "plugin_manager.h"
+#include "path_manager.h"
+#include "log_manager.h"
+
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+static const char* __FRAMEWORK_DIR = __STR(FRAMEWORK_DIR);
+#undef __STR
+#undef __XSTR
+
+namespace tizen {
+namespace runtime {
+namespace dotnetcore {
+
+#if defined (__aarch64__)
+#define ARCHITECTURE_IDENTIFIER "arm64"
+
+#elif defined (__arm__)
+#define ARCHITECTURE_IDENTIFIER "armel"
+
+#elif defined (__x86_64__)
+#define ARCHITECTURE_IDENTIFIER "x64"
+
+#elif defined (__i386__)
+#define ARCHITECTURE_IDENTIFIER "x86"
+
+#else
+#error "Unknown target"
+#endif
+
+static const char* __TIZEN_RID_VERSION_KEY = "db/dotnet/tizen_rid_version";
+
+// The sequence of RID_FALLBACK graphs must be:
+// 1. Tizen + Version + Architecture
+// 2. Tizen + Version
+// 3. OS(tizen, linux, unix) + Architecture
+// 4. OS(tizen, linux, unix)
+// 5. any, base
+static std::string getExtraNativeLibDirs(const std::string& appRoot)
+{
+       std::vector<std::string> RID_FALLBACK_GRAPH;
+       std::vector<std::string> RID_FALLBACK_TIZEN;
+       char* tizen_rid = vconf_get_str(__TIZEN_RID_VERSION_KEY);
+       if (tizen_rid) {
+               std::vector<std::string> version;
+               splitPath(tizen_rid, version);
+               std::reverse(std::begin(version), std::end(version));
+               for (unsigned int i = 0; i < version.size(); i++) {
+                       RID_FALLBACK_TIZEN.push_back(std::string("tizen." + version[i] + "-" + ARCHITECTURE_IDENTIFIER));
+                       RID_FALLBACK_TIZEN.push_back(std::string("tizen." + version[i]));
+               }
+               free(tizen_rid);
+       }
+
+       std::vector<std::string> RID_FALLBACK_OS = {"tizen", "linux", "unix"};
+       for (unsigned int i = 0; i < RID_FALLBACK_OS.size(); i++) {
+               RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i] + "-" +  ARCHITECTURE_IDENTIFIER));
+               RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i]));
+       }
+       RID_FALLBACK_GRAPH.push_back("any");
+       RID_FALLBACK_GRAPH.push_back("base");
+
+       std::string candidate;
+       for (unsigned int i = 0; i < RID_FALLBACK_GRAPH.size(); i++) {
+               if (!candidate.empty()) {
+                       candidate += ":";
+               }
+               candidate += concatPath(appRoot, "bin/runtimes/" + RID_FALLBACK_GRAPH[i] + "/native");
+       }
+
+       candidate = candidate + ":" + concatPath(appRoot, "lib/" ARCHITECTURE_IDENTIFIER);
+       if (!strncmp(ARCHITECTURE_IDENTIFIER, "arm64", 5)) {
+               candidate = candidate + ":" + concatPath(appRoot, "lib/aarch64");
+       } else if (!strncmp(ARCHITECTURE_IDENTIFIER, "armel", 5)) {
+               candidate = candidate + ":" + concatPath(appRoot, "lib/arm");
+       }
+
+       return candidate;
+}
+
+
+static std::vector<std::string> __envList;
+
+static void setEnvFromFile()
+{
+       std::string envList;
+       std::ifstream inFile(ENV_FILE_PATH);
+
+       __envList.clear();
+
+       if (inFile) {
+               _INFO("coreclr_env.list is found");
+
+               std::string token;
+               while (std::getline(inFile, token, '\n')) {
+                       if (!token.empty()) {
+                               __envList.push_back(token);
+                       }
+               }
+
+               for (unsigned int i = 0; i < __envList.size(); i++) {
+                       putenv(const_cast<char *>(__envList[i].c_str()));
+               }
+       } else {
+               _INFO("coreclr_env.list file is not found. skip");
+       }
+}
+
+#define _unused(x) ((void)(x))
+
+struct sigaction sig_abrt_new;
+struct sigaction sig_abrt_old;
+
+static bool checkOnSigabrt = false;
+static bool checkOnTerminate = false;
+
+static void onSigabrt(int signum)
+{
+       // use unused variable to avoid build warning
+       ssize_t ret = write(STDERR_FILENO, "onSigabrt called\n", 17);
+
+       if (checkOnTerminate) {
+               ret = write(STDERR_FILENO, "onSigabrt called while terminate. go to exit\n", 45);
+               _unused(ret);
+               exit(0);
+       }
+
+       if (checkOnSigabrt) {
+               ret = write(STDERR_FILENO, "onSigabrt called again. go to exit\n", 35);
+               _unused(ret);
+               exit(0);
+       }
+
+       checkOnSigabrt = true;
+       if (sigaction(SIGABRT, &sig_abrt_old, NULL) == 0) {
+               if (raise(signum) < 0) {
+                       ret = write(STDERR_FILENO, "Fail to raise SIGABRT\n", 22);
+               }
+       } else {
+               ret = write(STDERR_FILENO, "Fail to set original SIGABRT handler\n", 37);
+       }
+       _unused(ret);
+}
+
+static void registerSigHandler()
+{
+       sig_abrt_new.sa_handler = onSigabrt;
+       if (sigemptyset(&sig_abrt_new.sa_mask) != 0) {
+               _ERR("Fail to sigemptyset");
+       }
+
+       if (sigaction(SIGABRT, &sig_abrt_new, &sig_abrt_old) < 0) {
+               _ERR("Fail to add sig handler");
+       }
+}
+
+static bool storage_cb(int id, storage_type_e type, storage_state_e state, const char *path, void *user_data)
+{
+       int* tmp = (int*)user_data;
+       if (type == STORAGE_TYPE_INTERNAL)
+       {
+               *tmp = id;
+               return false;
+       }
+
+       return true;
+}
+
+static void initEnvForSpecialFolder()
+{
+       int storageId;
+       int error;
+       char *path = NULL;
+
+       error = storage_foreach_device_supported(storage_cb, &storageId);
+       if (error != STORAGE_ERROR_NONE) {
+               return;
+       }
+
+       error = storage_get_directory(storageId, STORAGE_DIRECTORY_IMAGES, &path);
+       if (error == STORAGE_ERROR_NONE && path != NULL) {
+               setenv("XDG_PICTURES_DIR", const_cast<char *>(path), 1);
+               free(path);
+               path = NULL;
+       }
+
+       error = storage_get_directory(storageId, STORAGE_DIRECTORY_MUSIC, &path);
+       if (error == STORAGE_ERROR_NONE && path != NULL) {
+               setenv("XDG_MUSIC_DIR", const_cast<char *>(path), 1);
+               free(path);
+               path = NULL;
+       }
+
+       error = storage_get_directory(storageId, STORAGE_DIRECTORY_VIDEOS, &path);
+       if (error == STORAGE_ERROR_NONE && path != NULL) {
+               setenv("XDG_VIDEOS_DIR", const_cast<char *>(path), 1);
+               free(path);
+               path = NULL;
+       }
+}
+
+// terminate candidate process when language changed
+// icu related data (CultureInfo, etc) should be recreated.
+static void langChangedCB(keynode_t *key, void* data)
+{
+       _INFO("terminiate candidate process to update language.");
+       exit(0);
+}
+
+static void setLang()
+{
+       char* lang = vconf_get_str(VCONFKEY_LANGSET);
+       if (!lang) {
+               _ERR("Fail to get language from vconf");
+               return;
+       }
+
+       // In order to operate ICU (used for globalization) normally, the following
+       // environment variables must be set before using ICU API.
+       // When running Applicaiton, the following environment variables are set by AppFW.
+       // But when preloading the dll in the candidate process, the following environment variables are not set
+       // As a result, CultureInfo is incorrectly generated and malfunctions.
+       // For example, uloc_getDefault() returns en_US_POSIX, CultureInfo is set to invariant mode.
+       setenv("LANG", const_cast<char *>(lang), 1);
+       setenv("LC_MESSAGES", const_cast<char *>(lang), 1);
+       setenv("LC_ALL", const_cast<char *>(lang), 1);
+
+       free(lang);
+}
+
+void CoreRuntime::preloadTypes()
+{
+       const static std::string initDllPath = concatPath(__FRAMEWORK_DIR, "Tizen.Init.dll");
+       if (!isFileExist(initDllPath)) {
+               _ERR("Failed to locate Tizen.Init.dll");
+               return;
+       }
+
+       typedef void (*InitDelegate)();
+       InitDelegate initDelegate;
+
+       int ret = createDelegate(__hostHandle,
+               __domainId,
+               "Tizen.Init",
+               "Tizen.Init.TypeLoader",
+               "PreloadTypes",
+               (void**)&initDelegate);
+
+       if (ret < 0) {
+               _ERR("Failed to create delegate for PreloadTypes (0x%08x)", ret);
+       } else {
+               initDelegate();
+       }
+}
+
+CoreRuntime::CoreRuntime(const char* mode) :
+       initializeClr(nullptr),
+       executeAssembly(nullptr),
+       shutdown(nullptr),
+       createDelegate(nullptr),
+       setEnvironmentVariable(nullptr),
+       __coreclrLib(nullptr),
+       __hostHandle(nullptr),
+       __domainId(-1),
+       __fd(-1),
+       __initialized(false),
+       __isProfileMode(false)
+{
+       _INFO("Constructor called!!");
+
+       // Intiailize ecore first (signal handlers, etc.) before runtime init.
+       ecore_init();
+
+       // set language environment to support ICU
+       setLang();
+
+       char *env = nullptr;
+       env = getenv("CORECLR_ENABLE_PROFILING");
+       if (env != nullptr && !strcmp(env, "1")) {
+               _INFO("profiling mode on");
+               __isProfileMode = true;
+       }
+
+       // plugin initialize should be called before start loader mainloop.
+       // In case of VD plugins, attaching secure zone is done in the plugin_initialize().
+       // When attaching to a secure zone, if there is a created thread, it will failed.
+       // So, plugin initialize should be called before mainloop start.
+       if (initializePluginManager(mode) < 0) {
+               _ERR("Failed to initialize PluginManager");
+       }
+}
+
+CoreRuntime::~CoreRuntime()
+{
+       // workaround : to prevent crash while process terminate on profiling mode,
+       //              kill process immediately.
+       // see https://github.com/dotnet/coreclr/issues/26687
+       if (__isProfileMode) {
+               _INFO("shutdown process immediately.");
+               _exit(0);
+       }
+
+       dispose();
+}
+
+int CoreRuntime::initialize(LaunchMode launchMode, bool useDlog, const char* rootPath)
+{
+       // checkInjection checks dotnet-launcher run mode
+       // At the moment, this mechanism is used only when the Memory Profiler is started.
+       int res = checkInjection();
+       if (res != 0) {
+               _ERR("Failed to initnialize Memory Profiler");
+               return -1;
+       }
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+
+#ifdef NATIVE_LIB_DIR
+       __nativeLibDirectory = __STR(NATIVE_LIB_DIR);
+#endif
+
+#undef __STR
+#undef __XSTR
+
+#ifdef __arm__
+       // libunwind library is used to unwind stack frame, but libunwind for ARM
+       // does not support ARM vfpv3/NEON registers in DWARF format correctly.
+       // Therefore let's disable stack unwinding using DWARF information
+       // See https://github.com/dotnet/coreclr/issues/6698
+       //
+       // libunwind use following methods to unwind stack frame.
+       // UNW_ARM_METHOD_ALL          0xFF
+       // UNW_ARM_METHOD_DWARF        0x01
+       // UNW_ARM_METHOD_FRAME        0x02
+       // UNW_ARM_METHOD_EXIDX        0x04
+       putenv(const_cast<char *>("UNW_ARM_UNWIND_METHOD=6"));
+#endif // __arm__
+
+       // Disable debug pipes and semaphores creation in case of non-standlone mode
+       if (launchMode == LaunchMode::loader)
+               putenv(const_cast<char *>("COMPlus_EnableDiagnostics=0"));
+
+       // Write Debug.WriteLine to stderr
+       putenv(const_cast<char *>("COMPlus_DebugWriteToStdErr=1"));
+
+#ifdef USE_DEFAULT_BASE_ADDR
+       putenv(const_cast<char *>("COMPlus_UseDefaultBaseAddr=1"));
+#endif // USE_DEFAULT_BASE_ADDR
+
+       // read string from external file and set them to environment value.
+       setEnvFromFile();
+
+       if (initializePathManager(std::string(), std::string(), std::string()) < 0) {
+               _ERR("Failed to initialize PathManager");
+               return -1;
+       }
+
+       if (useDlog && !pluginHasLogControl()) {
+               if (initializeLogManager() < 0) {
+                       _ERR("Failed to initnialize LogManager");
+                       return -1;
+               }
+       }
+
+       std::string libCoreclr(concatPath(getRuntimeDir(), "libcoreclr.so"));
+
+       __coreclrLib = dlopen(libCoreclr.c_str(), RTLD_NOW | RTLD_LOCAL);
+       if (__coreclrLib == nullptr) {
+               char *err = dlerror();
+               _ERR("dlopen failed to open libcoreclr.so with error %s", err);
+               if (access(libCoreclr.c_str(), R_OK) == -1)
+                       _ERR("access '%s': %s\n", libCoreclr.c_str(), strerror(errno));
+               return -1;
+       }
+
+#define CORELIB_RETURN_IF_NOSYM(type, variable, name) \
+       do { \
+               variable = (type)dlsym(__coreclrLib, name); \
+               if (variable == nullptr) { \
+                       _ERR(name " is not found in the libcoreclr.so"); \
+                       return -1; \
+               } \
+       } while (0)
+
+       CORELIB_RETURN_IF_NOSYM(coreclr_initialize_ptr, initializeClr, "coreclr_initialize");
+       CORELIB_RETURN_IF_NOSYM(coreclr_execute_assembly_ptr, executeAssembly, "coreclr_execute_assembly");
+       CORELIB_RETURN_IF_NOSYM(coreclr_shutdown_ptr, shutdown, "coreclr_shutdown");
+       CORELIB_RETURN_IF_NOSYM(coreclr_create_delegate_ptr, createDelegate, "coreclr_create_delegate");
+
+#undef CORELIB_RETURN_IF_NOSYM
+
+       _INFO("libcoreclr dlopen and dlsym success");
+
+       if (launchMode == LaunchMode::loader) {
+               pluginPreload();
+
+               // terminate candidate process if language is changed.
+               // CurrentCulture created for preloaded dlls should be updated.
+               vconf_notify_key_changed(VCONFKEY_LANGSET, langChangedCB, NULL);
+       }
+
+       // Set environment for System.Environment.SpecialFolder
+       // Below function creates dbus connection by callging storage API.
+       // If dbus connection is created bofere fork(), forked process cannot use dbus.
+       // To avoid gdbus blocking issue, below function should be called after fork()
+       initEnvForSpecialFolder();
+
+       std::string tpa = getTPA();
+       std::string runtimeDir = getRuntimeDir();
+       std::string appName = std::string("dotnet-launcher-") + std::to_string(getpid());
+       std::string probePath;
+       std::string NIprobePath;
+       std::string nativeLibPath;
+
+       if (launchMode == LaunchMode::corerun) {
+               probePath = rootPath;
+               NIprobePath = rootPath;
+               nativeLibPath = rootPath;
+       } else  {
+               __fd = open("/proc/self", O_DIRECTORY);
+               if (__fd < 0) {
+                       _ERR("Failed to open /proc/self");
+                       return -1;
+               }
+               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 appTac = concatPath(appBin, TAC_SYMLINK_SUB_DIR);
+               probePath = appRoot + ":" + appBin + ":" + appLib + ":" + appTac;
+               NIprobePath = concatPath(appBin, APP_NI_SUB_DIR) + ":" + concatPath(appLib, APP_NI_SUB_DIR) + ":" + appTac;
+               nativeLibPath = getExtraNativeLibDirs(appRoot) + ":" + appBin + ":" + appLib + ":" + __nativeLibDirectory + ":" + runtimeDir;
+       }
+
+       if (!initializeCoreClr(appName.c_str(), probePath.c_str(), NIprobePath.c_str(), nativeLibPath.c_str(), tpa.c_str())) {
+               _ERR("Failed to initialize coreclr");
+               return -1;
+       }
+
+       int st = createDelegate(__hostHandle, __domainId, "Dotnet.Launcher", "Dotnet.Launcher.Environment", "SetEnvironmentVariable", (void**)&setEnvironmentVariable);
+       if (st < 0 || setEnvironmentVariable == nullptr) {
+               _ERR("Create delegate for Dotnet.Launcher.dll -> Dotnet.Launcher.Environment -> SetEnvironmentVariable failed (0x%08x)", st);
+               return -1;
+       }
+
+       __initialized = true;
+
+       if (launchMode == LaunchMode::loader) {
+               preloadTypes();         // Preload common managed code
+       }
+
+       _INFO("CoreRuntime initialize success");
+
+       return 0;
+}
+
+bool CoreRuntime::initializeCoreClr(const char* appId,
+                                                                        const char* assemblyProbePaths,
+                                                                        const char* NIProbePaths,
+                                                                        const char* pinvokeProbePaths,
+                                                                        const char* tpaList)
+{
+       const char *propertyKeys[] = {
+               "TRUSTED_PLATFORM_ASSEMBLIES",
+               "APP_PATHS",
+               "APP_NI_PATHS",
+               "NATIVE_DLL_SEARCH_DIRECTORIES",
+               "AppDomainCompatSwitch"
+       };
+
+       const char *propertyValues[] = {
+               tpaList,
+               assemblyProbePaths,
+               NIProbePaths,
+               pinvokeProbePaths,
+               "UseLatestBehaviorWhenTFMNotSpecified"
+       };
+
+       std::string selfPath = readSelfPath();
+
+       int st = initializeClr(selfPath.c_str(),
+                                                       appId,
+                                                       sizeof(propertyKeys) / sizeof(propertyKeys[0]),
+                                                       propertyKeys,
+                                                       propertyValues,
+                                                       &__hostHandle,
+                                                       &__domainId);
+
+       if (st < 0) {
+               _ERR("initialize core clr fail! (0x%08x)", st);
+               return false;
+       }
+
+       pluginSetCoreclrInfo(__hostHandle, __domainId, createDelegate);
+
+       _INFO("Initialize core clr success");
+       return true;
+}
+
+void CoreRuntime::dispose()
+{
+       // call plugin finalize function to notify finalize to plugin
+       // dlclose shoud be done after coreclr shutdown to avoid breaking signal chain
+       pluginFinalize();
+
+       // ignore the signal generated by an exception that occurred during shutdown
+       checkOnTerminate = true;
+
+       if (__hostHandle != nullptr) {
+               int st = shutdown(__hostHandle, __domainId);
+               if (st < 0)
+                       _ERR("shutdown core clr fail! (0x%08x)", st);
+               __hostHandle = nullptr;
+       }
+
+       if (__coreclrLib != nullptr) {
+               if (dlclose(__coreclrLib) != 0) {
+                       _ERR("libcoreclr.so close failed");
+               }
+
+               __coreclrLib = nullptr;
+       }
+
+       finalizePluginManager();
+       finalizePathManager();
+
+       __envList.clear();
+
+       _INFO("Dotnet runtime disposed");
+}
+
+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 -1;
+       }
+
+       if (!isFileExist(path)) {
+               _ERR("File not exist : %s", path);
+               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 LogManager is not initialized, below redirectFD will return 0;
+       if (redirectFD() < 0) {
+               _ERR("Failed to redirect FD");
+               return -1;
+       }
+
+       // VD has their own signal handler.
+       if (!pluginHasLogControl()) {
+               registerSigHandler();
+       }
+
+       pluginSetAppInfo(appId, path);
+
+       // override root path for application launch mode (candidate / standalone mode)
+       if (__fd >= 0) {
+               int fd2 = open(root, O_DIRECTORY);
+               dup3(fd2, __fd, O_CLOEXEC);
+               if (fd2 >= 0)
+                       close(fd2);
+       }
+
+       // set application data path to coreclr environment.
+       // application data path can be changed by owner. So, we have to set data path just before launching.
+       char* localDataPath = app_get_data_path();
+       if (localDataPath != nullptr) {
+               setEnvironmentVariable("XDG_DATA_HOME", localDataPath);
+               free(localDataPath);
+       }
+
+       vconf_ignore_key_changed(VCONFKEY_LANGSET, langChangedCB);
+
+       pluginBeforeExecute();
+
+       _INFO("execute assembly : %s", path);
+
+       unsigned int ret = 0;
+       int st = executeAssembly(__hostHandle, __domainId, argc, (const char**)argv, path, &ret);
+       if (st < 0)
+               _ERR("Failed to Execute Assembly %s (0x%08x)", path, st);
+       return ret;
+}
+
+}  // namespace dotnetcore
+}  // namespace runtime
+}  // namespace tizen
diff --git a/NativeLauncher/launcher/lib/dotnet_launcher.h b/NativeLauncher/launcher/lib/dotnet_launcher.h
new file mode 100644 (file)
index 0000000..8f6c22a
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __DOTNET_LAUNCHER_H__
+#define __DOTNET_LAUNCHER_H__
+
+#include <string>
+
+#include "coreclr_host.h"
+#include "plugin_manager.h"
+
+enum LaunchMode {
+       corerun = 0,
+       loader,
+       launcher
+};
+
+namespace tizen {
+namespace runtime {
+namespace dotnetcore {
+
+class CoreRuntime
+{
+       public:
+               CoreRuntime(const char* mode);
+               ~CoreRuntime();
+               int initialize(LaunchMode mode, bool useDlog, const char* rootPath);
+               void dispose();
+               int launch(const char* appId, const char* root, const char* path, int argc, char* argv[]);
+
+       private:
+               bool initializeCoreClr(const char* appId, const char* assemblyProbePaths, const char* NIProbePaths, const char* pinvokeProbePaths, const char* tpaList);
+               void preloadTypes();
+               coreclr_initialize_ptr initializeClr;
+               coreclr_execute_assembly_ptr executeAssembly;
+               coreclr_shutdown_ptr shutdown;
+               coreclr_create_delegate_ptr createDelegate;
+               set_environment_variable_ptr setEnvironmentVariable;
+               std::string __nativeLibDirectory;
+               void* __coreclrLib;
+               void* __hostHandle;
+               unsigned int __domainId;
+               int __fd;
+               bool __initialized;
+               bool __isProfileMode;
+
+};
+
+}  // dotnetcore
+}  // namespace runtime
+}  // namespace tizen
+
+#endif /* __DOTNET_LAUNCHER_H__ */
diff --git a/NativeLauncher/launcher/lib/injection.cc b/NativeLauncher/launcher/lib/injection.cc
new file mode 100644 (file)
index 0000000..819af59
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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 "log.h"
+
+#include <cstdlib>
+#include <cstring>
+
+#include <dlfcn.h>
+
+#define HT_PATH "/home/owner/share/tmp/sdk_tools/heaptrack/"
+#define HT_LIB_PATH HT_PATH "libprofiler.so"
+#define HT_INJECTION_LIB_PATH HT_PATH "libheaptrack_inject.so"
+
+static int injectLibrary(const char path[])
+{
+       typedef int inject_func();
+
+       int res = -1;
+       void *lib = nullptr;
+       inject_func *inject = nullptr;
+       const char *inject_sym = "dotnet_launcher_inject";
+
+       _INFO("Inject %s library", path);
+
+       // Current implementation of heaptrack CLR profiler requires RTLD_GLOBAL
+       lib = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
+       if (lib == nullptr) {
+               _ERR("%s", dlerror());
+               return res;
+       }
+
+       inject = reinterpret_cast<inject_func*>(dlsym(lib, inject_sym));
+       if (inject == nullptr) {
+               _ERR("%s is not found in the %s", inject_sym, path);
+               return res;
+       }
+
+       res = inject();
+       return res;
+}
+
+int checkInjection()
+{
+       char *env = nullptr;
+
+       env = getenv("CORECLR_PROFILER_PATH");
+       if (env == nullptr) {
+               return 0;
+       }
+
+       // At the moment, this mechanism is used only when the Memory Profiler is started.
+       if (strcmp(env, HT_LIB_PATH) != 0) {
+               return 0;
+       }
+
+       _INFO("##### Perform injection #########");
+
+       if (injectLibrary(HT_INJECTION_LIB_PATH) != 0) {
+               _INFO("##### Injection failed #########");
+               return -1;
+       }
+
+       _INFO("##### Injection finished #########");
+       return 0;
+}
diff --git a/NativeLauncher/launcher/lib/injection.h b/NativeLauncher/launcher/lib/injection.h
new file mode 100644 (file)
index 0000000..6bcf111
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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 __INJETION_INTERFACE_H__
+#define __INJETION_INTERFACE_H__
+
+int checkInjection();
+
+#endif // __INJETION_INTERFACE_H__
diff --git a/NativeLauncher/launcher/main.cc b/NativeLauncher/launcher/main.cc
deleted file mode 100644 (file)
index 42ca9f4..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "dotnet/dotnet_launcher.h"
-#include "utils.h"
-#include "log.h"
-
-#include <cstdio>
-#include <vector>
-#include <memory>
-
-#include <Eina.h>
-#include <aul.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-// By the specification, application id must be shorter than 50 characters.
-// Current length of argv[0] is 25 with a space. ("/usr/bin/dotnet-launcher ")
-// To be able to change argv[0] when standalone mode padding for executable path is added.
-#define APPID_MAX_LENGTH       (25 + 105)
-
-static std::string StandaloneOption("--standalone");
-static std::string PaddingOption("--PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE");
-
-extern "C" int realMain(int argc, char *argv[], const char* mode)
-{
-       int i;
-       bool standaloneMode = false;
-       char* standalonePath = nullptr;
-       bool corerunMode = false;
-       bool paddingExist = false;
-
-       std::vector<char*> vargs;
-
-       // start index 1 to avoid passing executable name "dotnet-launcher" as a parameter
-       for (i = 1; i < argc; i++) {
-               if (StandaloneOption.compare(argv[i]) == 0) {
-                       standaloneMode = true;
-
-                       if (i > argc - 1) {
-                               fprintf(stderr, "Assembly path must be after \"--standalone\" option\n");
-                               return 1;
-                       }
-                       i++;
-                       standalonePath = argv[i];
-               } else if (PaddingOption.compare(argv[i]) == 0) {
-                       paddingExist = true;
-               } else {
-                       vargs.push_back(argv[i]);
-               }
-       }
-
-       if (isManagedAssembly(argv[1]) || isNativeImage(argv[1])) {
-               corerunMode = true;
-       }
-
-       using tizen::runtime::Launchpad;
-       using tizen::runtime::AppInfo;
-       using tizen::runtime::dotnetcore::CoreRuntime;
-
-       std::unique_ptr<CoreRuntime> runtime(new CoreRuntime(mode));
-
-       if (corerunMode) {
-               _INFO("##### Run in corerun mode #####");
-               char appId[APPID_MAX_LENGTH] = {0,};
-               std::string appRoot;
-               snprintf(appId, 16, "%s", "dotnet-launcher");
-               std::string absoluteDllPath = absolutePath(argv[1]);
-               appRoot = baseName(absoluteDllPath);
-
-               if (runtime->initialize(true, false, appRoot.c_str()) != 0) {
-                       _ERR("Failed to initialize");
-                       return 1;
-               }
-
-               int argsLen = vargs.size() - 1;
-               char** args = &vargs[1];
-               if (runtime->launch(appId, appRoot.c_str(), absoluteDllPath.c_str(), argsLen, args)) {
-                       _ERR("Failed to launch");
-                       return 1;
-               }
-       } else if (standaloneMode) {
-               _INFO("##### Run in standalone mode #####");
-               char appId[APPID_MAX_LENGTH] = {0,};
-               std::string appRoot;
-               if (AUL_R_OK == aul_app_get_appid_bypid(getpid(), appId, sizeof(appId))) {
-                       const char* appRootPath = aul_get_app_root_path();
-                       if (appRootPath != nullptr)
-                               appRoot = std::string(appRootPath);
-               } else {
-                       // If appId is not set, it is executed directly by cmdline.
-                       // In this case, appRoot is passed as an argument.
-                       snprintf(appId, 16, "%s", "dotnet-launcher");
-                       appRoot = baseName(baseName(standalonePath));
-               }
-               _INFO("AUL_APPID : %s", appId);
-
-               if (runtime->initialize(true, true, NULL) != 0) {
-                       _ERR("Failed to initialize");
-                       return 1;
-               }
-
-               // change cmdline from dotnet-launcher to executable path
-               int cmdlineSize = paddingExist ? APPID_MAX_LENGTH : APPID_MAX_LENGTH - PaddingOption.length();
-               memset(argv[0], '\0', cmdlineSize);
-               snprintf(argv[0], cmdlineSize, "%s", standalonePath);
-
-               int argsLen = vargs.size();
-               char** args = &vargs[0];
-               if (runtime->launch(appId, appRoot.c_str(), standalonePath, argsLen, args)) {
-                       _ERR("Failed to launch");
-                       return 1;
-               }
-       } else {
-               // change cmdline from dotnet-hydra-launcher to dotnet-launcher
-               if (strcmp(argv[0], "/usr/bin/dotnet-hydra-launcher") == 0) {
-                       memset(argv[0], '\0', strlen("/usr/bin/dotnet-hydra-launcher"));
-                       snprintf(argv[0], strlen("/usr/bin/dotnet-launcher") + 1, "/usr/bin/dotnet-launcher");
-               }
-
-               Launchpad.onCreate = [&runtime]() {
-                       if (runtime->initialize(false, true, NULL) != 0) {
-                               _ERR("Failed to initialized");
-                       } else {
-                               _INFO("Success to initialized");
-                       }
-               };
-
-               Launchpad.onTerminate = [&runtime](const AppInfo& appInfo, int argc, char** argv) {
-                       _INFO("launch request with app path : %s", appInfo.path.c_str());
-                       _INFO("appId : %s", appInfo.id.c_str());
-                       _INFO("pkg : %s", appInfo.pkg.c_str());
-
-                       // aul_get_app_root_path() can return NULL for error case.
-                       if (appInfo.root.empty()) {
-                               _ERR("Failed to launch. root path is set to NULL");
-                       } else {
-                               // The launchpad pass the name of exe file to the first argument.
-                               // For the C# spec, we have to skip this first argument.
-                               if (runtime->launch(appInfo.id.c_str(), appInfo.root.c_str(), appInfo.path.c_str(), argc-1, argv+1))
-                                       _ERR("Failed to launch");
-                       }
-               };
-               int ret = Launchpad.loaderMain(argc, argv);
-               if (ret < 0) {
-                       _ERR("fail to start loaderMain. candidate process is not created.");
-                       return 1;
-               }
-       }
-
-       return 0;
-}
-
-int main(int argc, char *argv[])
-{
-       return realMain(argc, argv, "default");
-}
index 2c2951843c725977dad6909e7f84cf9fabb4b08b..014f7601a7b9ca43c64a7d7d79d7339bff29d4f0 100644 (file)
@@ -23,6 +23,7 @@
 #include <pkgmgr-info.h>
 #include <pkgmgr_installer_info.h>
 #include <sys/smack.h>
+#include <sys/prctl.h>
 
 #include <cstdlib>
 #include <cstring>
@@ -596,3 +597,29 @@ bool removeAll(const bf::path& path) {
        }
        return true;
 }
+
+void setCmdName(const char* name)
+{
+       #define PRC_NAME_LENGTH         16
+
+       char processName[PRC_NAME_LENGTH] = {0, };
+
+       if (name == NULL || *name == '\0') {
+               return;
+       }
+
+       memset(processName, '\0', PRC_NAME_LENGTH);
+       snprintf(processName, PRC_NAME_LENGTH, "%s", name);
+       prctl(PR_SET_NAME, processName);                
+}
+
+char* getFileNameFromPath(char* path)
+{
+       char* fileName = strrchr(path, PATH_SEPARATOR);
+       if (fileName != NULL && *fileName != '\0') {
+               return ++fileName;
+       }
+
+       return NULL;
+}
+
index 0f2e9fc33f5c7fb3f6e9be7be0945a1acbec04ef..e14cc1f300fee1669726894eca6f12542934035a 100644 (file)
@@ -4,5 +4,7 @@
     </request>
     <assign>
         <filesystem path="/opt/usr/dotnet" label="System::Shared" type="transmutable" />
+        <filesystem path="/usr/bin/dotnet-loader" label="User" exec_label="User" />
+        <filesystem path="/usr/bin/dotnet" label="System::Tools" exec_label="User" />
     </assign>
 </manifest>
index a77161e3a59ec1d028255bf76ff8cdf111a7cd4c..e1fd6b1a72976da9eb8ee6605759d3bb46817468 100644 (file)
@@ -142,6 +142,9 @@ install -m 0644 %{name}.conf %{buildroot}/etc/tmpfiles.d/%{name}.conf
 mkdir -p /opt/etc/skel/.dotnet
 chsmack -t -a User::App::Shared /opt/etc/skel/.dotnet
 %{_bindir}/dotnettool --ni-dll %{_runtime_dir}/System.Private.CoreLib.dll
+setcap cap_setgid,cap_sys_admin+ei /usr/bin/dotnet-launcher
+setcap cap_setgid,cap_sys_admin+ei /usr/bin/dotnet-loader
+setcap cap_setgid,cap_sys_admin+ei /usr/bin/dotnet
 
 %files
 %manifest dotnet-launcher.manifest
@@ -156,8 +159,11 @@ chsmack -t -a User::App::Shared /opt/etc/skel/.dotnet
 %{_install_mdplugin_dir}/libprefer_nuget_cache_plugin.so
 %{_install_mdplugin_dir}/libprefer_dotnet_aot_plugin.so
 %{_bindir}/dotnet-launcher
-%{_bindir}/dotnet-hydra-launcher
+%{_bindir}/dotnet-loader
+%{_bindir}/dotnet
+%{_bindir}/dotnet-hydra-loader
 %{_libdir}/libdotnet_launcher_util.so
+%{_libdir}/libdotnet_launcher_core.so
 %{_libdir}/libni_common.so
 %{_libdir}/libtac_common.so
 /etc/tmpfiles.d/%{name}.conf