2 * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <launchpad_hydra.h>
28 #include <sys/types.h>
32 #include "launcher_env.h"
34 const char* __coreclr_lib = "/usr/share/dotnet.tizen/netcoreapp/libcoreclr.so";
35 const char* __dotnet_loader = "/usr/bin/dotnet-loader";
37 typedef int (*coreclr_preload_assembly_ptr)(const char* assemblyPath);
38 typedef int (*launcher_real_main_ptr)(int argc, char *argv[]);
40 static std::string getAbsolutePath(const std::string& path)
43 char *realPath = realpath(path.c_str(), NULL);
45 absPath.assign(realPath);
52 static bool isFile(const std::string& path)
55 return lstat(path.c_str(), &sb) == 0;
58 static std::string replaceAll(const std::string& str, const std::string& pattern, const std::string& replace)
60 std::string result = str;
61 std::string::size_type pos = 0;
62 std::string::size_type offset = 0;
64 while ((pos = result.find(pattern, offset)) != std::string::npos) {
65 result.replace(result.begin() + pos, result.begin() + pos + pattern.size(), replace);
66 offset = pos + replace.size();
72 static std::string findDllPath(const std::string& filename)
74 const std::string netcoreappDir = "/usr/share/dotnet.tizen/netcoreapp/";
75 const std::string frameworkDir = "/usr/share/dotnet.tizen/framework/";
79 // check whether the target file exist under netcoreapp directory
80 result = netcoreappDir + filename;
85 // check whether the target file exist under framework directory
86 result = frameworkDir + filename;
91 // dll file is not found. return empty string
97 static void preloadAssemblies()
99 #ifdef USE_DEFAULT_BASE_ADDR
100 putenv(const_cast<char *>("COMPlus_UseDefaultBaseAddr=1"));
101 #endif // USE_DEFAULT_BASE_ADDR
103 void* coreclrLib = dlopen(__coreclr_lib, RTLD_NOW | RTLD_GLOBAL);
104 if (coreclrLib == nullptr) {
105 _DBG("dlopen failed to open libcoreclr.so");
109 coreclr_preload_assembly_ptr preloadAssembly;
110 preloadAssembly = (coreclr_preload_assembly_ptr)dlsym(coreclrLib, "coreclr_preload_assembly");
111 if (preloadAssembly == nullptr) {
112 _DBG("coreclr_preload_assembly is not found in the libcoreclr.so");
116 const std::string preloadDir = "/usr/share/dotnet.tizen/preload/";
118 // get file list from preload directory
119 // file is sorted by std::set
120 std::set<std::string> preloadFiles;
121 DIR* dirp = opendir(preloadDir.c_str());
123 while ((dp = readdir(dirp)) != NULL) {
124 if (dp->d_type != DT_DIR) {
125 // Make sure that the file name follows naming conventions.
127 isdigit(dp->d_name[0]) &&
128 isdigit(dp->d_name[1]) &&
129 (dp->d_name[2] == '.')) {
130 preloadFiles.insert(preloadDir + dp->d_name);
136 // get dll list from each preload file, and preload dll.
137 std::set<std::string> dllList;
140 for (const auto& pf: preloadFiles) {
142 if (!ifs.is_open()) {
143 _ERR("failed to open preload file (%s)", pf.c_str());
147 while (std::getline(ifs, in_line)) {
148 in_line = in_line.substr(0, in_line.find_first_of(" ", 0));
150 // select dll file case
151 if (in_line[0] == '#' ||
154 (in_line.find(".dll") == std::string::npos)) {
158 // only native image should be passed as a parameter of coreclr_preload_assembly.
159 if (in_line.find(".ni.dll") == std::string::npos &&
160 in_line.compare("System.Private.CoreLib.dll")) {
161 in_line = replaceAll(in_line, ".dll", ".ni.dll");
164 // coreclr_preload_assembly cannot ignore duplicate loading.
165 // Therefore, only one dll should be preloaded.
166 // dllList is used to ignore duplicated loading request
167 if (dllList.insert(in_line).second) {
168 // check whether the target file exist under netcoreapp directory
169 std::string path = findDllPath(in_line);
171 int st = preloadAssembly(getAbsolutePath(path).c_str());
173 _ERR("preload of %s failed! (0x%08x)", path.c_str(), st);
175 _INFO("preload of %s succeeded", path.c_str());
178 _ERR("preload failed : file (%s) does not eixst", in_line.c_str());
187 int main(int argc, char** argv)
189 hydra_lifecycle_callback_s hydra_callback;
191 hydra_callback.precreate = [](void* user_data) {
192 _INFO("hydra : precreate");
196 hydra_callback.create = [](void* user_data) {
197 _INFO("hydra : create");
200 hydra_callback.fork = [](int argc, char **argv, void* user_data) -> int {
201 _INFO("hydra : fork");
202 void* launcher_h = dlopen(__dotnet_loader, RTLD_NOW | RTLD_GLOBAL);
203 if (launcher_h == nullptr) {
204 _DBG("dlopen failed to open dotnet-launcher");
208 launcher_real_main_ptr realMain = (launcher_real_main_ptr)dlsym(launcher_h, "realMain");
209 if (realMain == nullptr) {
210 _DBG("realMain is not found in the dotnet-launcher");
215 return realMain(argc, argv);
218 hydra_callback.terminate = [](void* user_data)-> int {
219 _INFO("hydra : terminate");
223 return launchpad_hydra_main(argc, argv, &hydra_callback, nullptr);