Refactoring CoreRuntime and plugin (#247) accepted/tizen/unified/20200630.131320 submit/tizen/20200629.221257
author조웅석/Common Platform Lab(SR)/Principal Engineer/삼성전자 <ws77.cho@samsung.com>
Mon, 29 Jun 2020 21:52:56 +0000 (06:52 +0900)
committer이형주/Common Platform Lab(SR)/Staff Engineer/삼성전자 <leee.lee@samsung.com>
Mon, 29 Jun 2020 21:52:56 +0000 (06:52 +0900)
* Pass apptype to plugin insteadof mode

The meaning of the mode that is delivered during plugin initialization is not clear.
And, VD plugin use mode to distinguish app-type.

So, change the parameter of plugin_initialize from mode to apptype.
Also, the script was modified to obtain the apptype in the candidate process.

The parameter of the CoreRuntime constructor was also unnecessary and deleted.

* Change CoreRuntime to static class

CoreRuntime is a wrapper class of .NET Runtime (coreclr),
So, that cannot be created with multiple instance, and cannot be called
multiple times.

So, I changed CoreRuntime to static class which contains only static functions.
Also, it was changed to explicitly call what was called as a destructor.

Additionally, some function name and file name have been changed.

NativeLauncher/CMakeLists.txt
NativeLauncher/dotnet.launcher
NativeLauncher/dotnet.loader
NativeLauncher/hydra/hydra_main.cc
NativeLauncher/inc/plugin_manager.h
NativeLauncher/launcher/exec/launcher.cc
NativeLauncher/launcher/exec/loader.cc
NativeLauncher/launcher/lib/core_runtime.cc [moved from NativeLauncher/launcher/lib/dotnet_launcher.cc with 93% similarity]
NativeLauncher/launcher/lib/core_runtime.h [moved from NativeLauncher/launcher/lib/dotnet_launcher.h with 51% similarity]
NativeLauncher/util/plugin_manager.cc

index 773686c..1252576 100644 (file)
@@ -117,7 +117,7 @@ TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER_UTIL} ${${PROJECT_NAME}_LDFLAGS} "-ldl"
 SET(DOTNET_LAUNCHER_CORE "dotnet_launcher_core")
 SET(${DOTNET_LAUNCHER_CORE}_SOURCE_FILES
     launcher/lib/injection.cc
-    launcher/lib/dotnet_launcher.cc
+    launcher/lib/core_runtime.cc
 )
 ADD_LIBRARY(${DOTNET_LAUNCHER_CORE} SHARED ${${DOTNET_LAUNCHER_CORE}_SOURCE_FILES})
 SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER_CORE} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_LIB})
index 0cd09a2..4bcd42d 100644 (file)
@@ -3,5 +3,7 @@ NAME         dotnet-launcher
 EXE          /usr/bin/dotnet-launcher
 APP_TYPE     dotnet
 EXTRA_ARG    --PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE
+EXTRA_ARG    --appType
+EXTRA_ARG    dotnet
 EXTRA_ARG    --standalone
 
index 3422bad..6cc183f 100644 (file)
@@ -9,3 +9,4 @@ DETECTION_METHOD       TIMEOUT|DEMAND
 TIMEOUT                5000
 ON_BOOT                OFF
 HYDRA                  OFF
+EXTRA                  --appType                dotnet
index 5b59cf3..3e45eb2 100644 (file)
@@ -35,7 +35,7 @@ const char* __coreclr_lib = "/usr/share/dotnet.tizen/netcoreapp/libcoreclr.so";
 const char* __dotnet_loader = "/usr/bin/dotnet-loader";
 
 typedef int (*coreclr_preload_assembly_ptr)(const char* assemblyPath);
-typedef int (*launcher_real_main_ptr)(int argc, char *argv[], const char* mode);
+typedef int (*launcher_real_main_ptr)(int argc, char *argv[]);
 
 static std::string getAbsolutePath(const std::string& path)
 {
@@ -212,7 +212,7 @@ int main(int argc, char** argv)
                        return -1;
                }
 
-               return realMain(argc, argv, "default");
+               return realMain(argc, argv);
        };
 
        hydra_callback.terminate = [](void* user_data)-> int {
index 2a8ff56..e00b628 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "coreclr_host.h"
 
-typedef void (*plugin_initialize_ptr)(const char* mode);
+typedef void (*plugin_initialize_ptr)(const char* appType);
 typedef void (*plugin_preload_ptr)();
 typedef void (*plugin_set_app_info_ptr)(
                        const char* appId,
@@ -57,7 +57,7 @@ void pluginBeforeExecute();
 void pluginFinalize();
 
 // initialize / finalize plugin manager
-int initializePluginManager(const char* mode);
+int initializePluginManager(const char* appType);
 void finalizePluginManager();
 
 #endif /* __PLUGIN_MANAGER_H__ */
index 37b0743..a302bb4 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "dotnet_launcher.h"
+#include "core_runtime.h"
 #include "utils.h"
 #include "log.h"
 
@@ -38,6 +38,7 @@ using tizen::runtime::dotnetcore::CoreRuntime;
 
 static std::string StandaloneOption("--standalone");
 static std::string PaddingOption("--PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE");
+static std::string AppTypeOption("--appType");
 
 int main(int argc, char *argv[])
 {
@@ -45,6 +46,7 @@ int main(int argc, char *argv[])
 
        char* standalonePath = nullptr;
        bool paddingExist = false;
+       const char* appType = NULL;
        const char* appRootPath = NULL;
        char appId[APPID_MAX_LENGTH] = {0,};
 
@@ -61,12 +63,21 @@ int main(int argc, char *argv[])
                        standalonePath = argv[i];
                } else if (PaddingOption.compare(argv[i]) == 0) {
                        paddingExist = true;
+               } else if (AppTypeOption.compare(argv[i]) == 0) {
+                       if (i > argc - 1) {
+                               _ERR("app type for launchpad must be after \"--appType\" option");
+                               return -1;
+                       }
+                       i++;
+                       appType = argv[i];
                } else {
                        vargs.push_back(argv[i]);
                }
        }
 
-       std::unique_ptr<CoreRuntime> runtime(new CoreRuntime("standalone"));
+       if (appType == NULL) {
+               appType = "dotnet";
+       }
 
        // get app ID and app root path
        if (AUL_R_OK == aul_app_get_appid_bypid(getpid(), appId, sizeof(appId))) {
@@ -90,17 +101,20 @@ int main(int argc, char *argv[])
        memset(argv[0], '\0', cmdlineSize);
        snprintf(argv[0], cmdlineSize - 1, "%s", standalonePath);
 
-       // initialize CoreRuntime (standalone mode enable, dlog redirection enable, root path NULL)
-       if (runtime->initialize(LaunchMode::launcher) != 0) {
+       // initialize CoreRuntime
+       if (CoreRuntime::initialize(appType, LaunchMode::launcher) != 0) {
                _ERR("Failed to initialize");
                return -1;
        }
 
        // launch application
-       if (runtime->launch(appId, appRootPath, standalonePath, vargs.size(), &vargs[0])) {
+       if (CoreRuntime::launch(appId, appRootPath, standalonePath, vargs.size(), &vargs[0])) {
                _ERR("Failed to launch");
                return -1;
        }
 
+       // finalize runtime
+       CoreRuntime::finalize();
+
        return 0;
 }
index 222de0a..0669593 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "dotnet_launcher.h"
+#include "core_runtime.h"
 #include "utils.h"
 #include "log.h"
 
@@ -32,6 +32,8 @@
 
 using tizen::runtime::dotnetcore::CoreRuntime;
 
+static const char* KEY_APP_TYPE = "--appType";
+
 static Ecore_Fd_Handler *__fd_handler;
 static loader_receiver_cb __receiver;
 
@@ -114,14 +116,12 @@ static void __adapter_remove_fd(void *user_data, int fd)
 
 static void __loader_create_cb(bundle *extra, int type, void *user_data)
 {
-       CoreRuntime* runtime = (CoreRuntime*)user_data;
-
-       {
-               // do native window precreation here
+       char *appType = NULL;
+       if (bundle_get_str(extra, KEY_APP_TYPE, &appType) != BUNDLE_ERROR_NONE) {
+               appType = NULL;
        }
 
-       // initialize CoreRuntime (launchmode, dlog redirection enable, root path NULL)
-       if (runtime->initialize(LaunchMode::loader) != 0) {
+       if (CoreRuntime::initialize(appType ? appType : "dotnet", LaunchMode::loader) != 0) {
                _ERR("Failed to initialized");
        } else {
                _INFO("Success to initialized");
@@ -146,15 +146,14 @@ static int __loader_launch_cb(int argc, char **argv, const char *app_path,
 
 static int __loader_terminate_cb(int argc, char **argv, void *user_data)
 {
-       CoreRuntime* runtime = (CoreRuntime*)user_data;
-
        _INFO("launch request with app path : %s", __appInfo.app_path.c_str());
 
        // The launchpad pass the name of exe file to the first argument.
        // For the C# spec, we have to skip this first argument.
-       if (runtime->launch(__appInfo.appid.c_str(), __appInfo.root.c_str(),
+       if (CoreRuntime::launch(__appInfo.appid.c_str(), __appInfo.root.c_str(),
                                                __appInfo.app_path.c_str(), argc - 1, argv + 1)) {
                _ERR("Failed to launch");
+               return -1;
        }
 
        return 0;
@@ -162,12 +161,10 @@ static int __loader_terminate_cb(int argc, char **argv, void *user_data)
 
 //################## Main Code #################################################
 
-extern "C" int realMain(int argc, char *argv[], const char* mode)
+extern "C" int realMain(int argc, char *argv[])
 {
        _INFO("##### Run in candidate mode #####");
 
-       CoreRuntime* runtime = new CoreRuntime(mode);
-
        // change cmdline from dotnet-hydra-loader to dotnet-loader
        if (strcmp(argv[0], "/usr/bin/dotnet-hydra-loader") == 0) {
                memset(argv[0], '\0', strlen("/usr/bin/dotnet-hydra-loader"));
@@ -190,8 +187,10 @@ extern "C" int realMain(int argc, char *argv[], const char* mode)
                .remove_fd = __adapter_remove_fd
        };
 
-       int ret = launchpad_loader_main(argc, argv, &callbacks, &adapter, runtime);
-       delete runtime;
+       int ret = launchpad_loader_main(argc, argv, &callbacks, &adapter, NULL);
+       if (ret >= 0) {
+               CoreRuntime::finalize();
+       }
 
        return ret;
 }
@@ -201,5 +200,5 @@ int main(int argc, char *argv[])
        __argc = argc;
        __argv = argv;
 
-       return realMain(argc, argv, "candidate");
+       return realMain(argc, argv);
 }
similarity index 93%
rename from NativeLauncher/launcher/lib/dotnet_launcher.cc
rename to NativeLauncher/launcher/lib/core_runtime.cc
index 0a32533..3fd90bb 100644 (file)
@@ -42,7 +42,7 @@
 #include "injection.h"
 #include "utils.h"
 #include "log.h"
-#include "dotnet_launcher.h"
+#include "core_runtime.h"
 #include "plugin_manager.h"
 #include "path_manager.h"
 #include "log_manager.h"
@@ -51,6 +51,28 @@ namespace tizen {
 namespace runtime {
 namespace dotnetcore {
 
+static coreclr_initialize_ptr initializeClr = nullptr;
+static coreclr_execute_assembly_ptr executeAssembly = nullptr;
+static coreclr_shutdown_ptr shutdown = nullptr;
+static coreclr_create_delegate_ptr createDelegate = nullptr;
+static set_environment_variable_ptr setEnvironmentVariable = nullptr;
+static void* __coreclrLib = nullptr;
+static void* __hostHandle = nullptr;
+static unsigned int __domainId = -1;
+static int __fd = -1;
+static bool __initialized = false;
+static bool __isProfileMode = false;
+
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+
+#ifdef NATIVE_LIB_DIR
+static std::string __nativeLibDirectory = __STR(NATIVE_LIB_DIR);
+#endif
+
+#undef __STR
+#undef __XSTR
+
 #if defined (__aarch64__)
 #define ARCHITECTURE_IDENTIFIER "arm64"
 
@@ -277,7 +299,7 @@ static std::string readSelfPath()
        return "";
 }
 
-void CoreRuntime::preload()
+void preload()
 {
        typedef void (*PreloadDelegate)();
        PreloadDelegate preloadDelegate;
@@ -296,20 +318,55 @@ void CoreRuntime::preload()
        }
 }
 
-CoreRuntime::CoreRuntime(const char* mode) :
-       initializeClr(nullptr),
-       executeAssembly(nullptr),
-       shutdown(nullptr),
-       createDelegate(nullptr),
-       setEnvironmentVariable(nullptr),
-       __coreclrLib(nullptr),
-       __hostHandle(nullptr),
-       __domainId(-1),
-       __fd(-1),
-       __initialized(false),
-       __isProfileMode(false)
+bool initializeCoreClr(const char* appId,
+                                                                        const char* assemblyProbePaths,
+                                                                        const char* NIProbePaths,
+                                                                        const char* pinvokeProbePaths,
+                                                                        const char* tpaList)
+{
+       const char *propertyKeys[] = {
+               "TRUSTED_PLATFORM_ASSEMBLIES",
+               "APP_PATHS",
+               "APP_NI_PATHS",
+               "NATIVE_DLL_SEARCH_DIRECTORIES",
+               "AppDomainCompatSwitch"
+       };
+
+       const char *propertyValues[] = {
+               tpaList,
+               assemblyProbePaths,
+               NIProbePaths,
+               pinvokeProbePaths,
+               "UseLatestBehaviorWhenTFMNotSpecified"
+       };
+
+       std::string selfPath = readSelfPath();
+
+       int st = initializeClr(selfPath.c_str(),
+                                                       appId,
+                                                       sizeof(propertyKeys) / sizeof(propertyKeys[0]),
+                                                       propertyKeys,
+                                                       propertyValues,
+                                                       &__hostHandle,
+                                                       &__domainId);
+
+       if (st < 0) {
+               _ERR("initialize core clr fail! (0x%08x)", st);
+               return false;
+       }
+
+       pluginSetCoreclrInfo(__hostHandle, __domainId, createDelegate);
+
+       _INFO("Initialize core clr success");
+       return true;
+}
+
+int CoreRuntime::initialize(const char* appType, LaunchMode launchMode)
 {
-       _INFO("Constructor called!!");
+       if (__initialized) {
+               _ERR("CoreRuntime is already initialized");
+               return -1;
+       }
 
        // Intiailize ecore first (signal handlers, etc.) before runtime init.
        ecore_init();
@@ -324,30 +381,14 @@ CoreRuntime::CoreRuntime(const char* mode) :
                __isProfileMode = true;
        }
 
-       // plugin initialize should be called before start loader mainloop.
+       // plugin initialize should be called before creating threads.
        // In case of VD plugins, attaching secure zone is done in the plugin_initialize().
        // When attaching to a secure zone, if there is a created thread, it will failed.
-       // So, plugin initialize should be called before mainloop start.
-       if (initializePluginManager(mode) < 0) {
+       // So, plugin initialize should be called before creating threads.
+       if (initializePluginManager(appType) < 0) {
                _ERR("Failed to initialize PluginManager");
        }
-}
 
-CoreRuntime::~CoreRuntime()
-{
-       // workaround : to prevent crash while process terminate on profiling mode,
-       //              kill process immediately.
-       // see https://github.com/dotnet/coreclr/issues/26687
-       if (__isProfileMode) {
-               _INFO("shutdown process immediately.");
-               _exit(0);
-       }
-
-       dispose();
-}
-
-int CoreRuntime::initialize(LaunchMode launchMode)
-{
        // checkInjection checks dotnet-launcher run mode
        // At the moment, this mechanism is used only when the Memory Profiler is started.
        int res = checkInjection();
@@ -355,15 +396,6 @@ int CoreRuntime::initialize(LaunchMode launchMode)
                _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
@@ -434,14 +466,6 @@ int CoreRuntime::initialize(LaunchMode launchMode)
 
        _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.
@@ -479,6 +503,11 @@ int CoreRuntime::initialize(LaunchMode launchMode)
        __initialized = true;
 
        if (launchMode == LaunchMode::loader) {
+               // terminate candidate process if language is changed.
+               // CurrentCulture created for preloaded dlls should be updated.
+               vconf_notify_key_changed(VCONFKEY_LANGSET, langChangedCB, NULL);
+
+               pluginPreload();
                preload();              // Preload common managed code
        }
 
@@ -487,51 +516,13 @@ int CoreRuntime::initialize(LaunchMode launchMode)
        return 0;
 }
 
-bool CoreRuntime::initializeCoreClr(const char* appId,
-                                                                        const char* assemblyProbePaths,
-                                                                        const char* NIProbePaths,
-                                                                        const char* pinvokeProbePaths,
-                                                                        const char* tpaList)
+void CoreRuntime::finalize()
 {
-       const char *propertyKeys[] = {
-               "TRUSTED_PLATFORM_ASSEMBLIES",
-               "APP_PATHS",
-               "APP_NI_PATHS",
-               "NATIVE_DLL_SEARCH_DIRECTORIES",
-               "AppDomainCompatSwitch"
-       };
-
-       const char *propertyValues[] = {
-               tpaList,
-               assemblyProbePaths,
-               NIProbePaths,
-               pinvokeProbePaths,
-               "UseLatestBehaviorWhenTFMNotSpecified"
-       };
-
-       std::string selfPath = readSelfPath();
-
-       int st = initializeClr(selfPath.c_str(),
-                                                       appId,
-                                                       sizeof(propertyKeys) / sizeof(propertyKeys[0]),
-                                                       propertyKeys,
-                                                       propertyValues,
-                                                       &__hostHandle,
-                                                       &__domainId);
-
-       if (st < 0) {
-               _ERR("initialize core clr fail! (0x%08x)", st);
-               return false;
+       if (!__initialized) {
+               _ERR("Runtime is not initialized");
+               return;
        }
 
-       pluginSetCoreclrInfo(__hostHandle, __domainId, createDelegate);
-
-       _INFO("Initialize core clr success");
-       return true;
-}
-
-void CoreRuntime::dispose()
-{
        // call plugin finalize function to notify finalize to plugin
        // dlclose shoud be done after coreclr shutdown to avoid breaking signal chain
        pluginFinalize();
@@ -539,6 +530,14 @@ void CoreRuntime::dispose()
        // ignore the signal generated by an exception that occurred during shutdown
        checkOnTerminate = true;
 
+       // workaround : to prevent crash while process terminate on profiling mode,
+       //              kill process immediately.
+       // see https://github.com/dotnet/coreclr/issues/26687
+       if (__isProfileMode) {
+               _INFO("shutdown process immediately.");
+               _exit(0);
+       }
+
        if (__hostHandle != nullptr) {
                int st = shutdown(__hostHandle, __domainId);
                if (st < 0)
@@ -559,7 +558,7 @@ void CoreRuntime::dispose()
 
        __envList.clear();
 
-       _INFO("Dotnet runtime disposed");
+       _INFO("CoreRuntime finalized");
 }
 
 int CoreRuntime::launch(const char* appId, const char* root, const char* path, int argc, char* argv[])
similarity index 51%
rename from NativeLauncher/launcher/lib/dotnet_launcher.h
rename to NativeLauncher/launcher/lib/core_runtime.h
index ddaabd6..27b97b9 100644 (file)
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef __DOTNET_LAUNCHER_H__
-#define __DOTNET_LAUNCHER_H__
+#ifndef __CORE_RUNTIME_H__
+#define __CORE_RUNTIME_H__
 
 #include <string>
 
@@ -35,31 +35,13 @@ namespace dotnetcore {
 class CoreRuntime
 {
        public:
-               CoreRuntime(const char* mode);
-               ~CoreRuntime();
-               int initialize(LaunchMode mode);
-               void dispose();
-               int launch(const char* appId, const char* root, const char* path, int argc, char* argv[]);
-
-       private:
-               bool initializeCoreClr(const char* appId, const char* assemblyProbePaths, const char* NIProbePaths, const char* pinvokeProbePaths, const char* tpaList);
-               void preload();
-               coreclr_initialize_ptr initializeClr;
-               coreclr_execute_assembly_ptr executeAssembly;
-               coreclr_shutdown_ptr shutdown;
-               coreclr_create_delegate_ptr createDelegate;
-               set_environment_variable_ptr setEnvironmentVariable;
-               std::string __nativeLibDirectory;
-               void* __coreclrLib;
-               void* __hostHandle;
-               unsigned int __domainId;
-               int __fd;
-               bool __initialized;
-               bool __isProfileMode;
+               static int initialize(const char* appType, LaunchMode launchMode);
+               static void finalize();
+               static int launch(const char* appId, const char* root, const char* path, int argc, char* argv[]);
 };
 
 }  // dotnetcore
 }  // namespace runtime
 }  // namespace tizen
 
-#endif /* __DOTNET_LAUNCHER_H__ */
+#endif /* __CORE_RUNTIME_H__ */
index e402576..d0e829e 100644 (file)
@@ -24,7 +24,7 @@ static PluginFunc* __pluginFunc = NULL;
 static void* __pluginLib;
 bool initializedPluginManager = false;
 
-int initializePluginManager(const char* mode)
+int initializePluginManager(const char* appType)
 {
        if (initializedPluginManager) {
                _INFO("Plugin manager already initialized");
@@ -51,10 +51,10 @@ int initializePluginManager(const char* mode)
                }
 
                if (__pluginFunc->initialize)
-                       __pluginFunc->initialize(mode);
+                       __pluginFunc->initialize(appType);
        }
 
-       _INFO("Plugin manager initialize success");
+       _INFO("Plugin manager initialize success : appType(%s)", appType);
 
        initializedPluginManager = true;
        return 0;