The launchpad debug is implemented using C++ language.
Change-Id: I13ed4cb60cfcf356d52748d3a2f3d53182ca2d23
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
#include "launchpad-process-pool/debug.hh"
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
#include <fstream>
+#include <utility>
+#include "lib/common/inc/key.h"
#include "lib/common/inc/launchpad_common.h"
+namespace fs = std::filesystem;
+
namespace launchpad {
+namespace {
+
+constexpr const char kAsanAppListPath[] =
+ "/opt/usr/share/aul/debug/.asan_app_list";
+constexpr const char kDebuggerInfoPath[] = "/run/share/aul";
+
+std::vector<std::string> GetStringArray(const tizen_base::Bundle& b,
+ const std::string& key) {
+ std::vector<std::string> values;
+ if (b.GetType(key) & BUNDLE_TYPE_ARRAY) {
+ values = b.GetStringArray(key);
+ } else {
+ std::string value = b.GetString(key);
+ if (!value.empty())
+ values.push_back(std::move(value));
+ }
+
+ return values;
+}
+
+} // namespace
+
+Debug& Debug::GetInst() {
+ static Debug inst;
+ inst.Init();
+ return inst;
+}
+
+void Debug::Dispose() {
+ if (disposed_)
+ return;
+
+ file_monitor_.reset();
+ disposed_ = true;
+}
+
+void Debug::Load() {
+ if (!debugger_infos_.empty())
+ return;
+
+ DebuggerInfoInflator inflator;
+ debugger_infos_ = inflator.Inflate(kDebuggerInfoPath);
+}
+
+void Debug::PrepareDebugger(const tizen_base::Bundle& b) {
+ auto debugger = b.GetString(AUL_K_SDK);
+ if (debugger.empty())
+ return;
+
+ _D("[DEBUG] Debugger: %s", debugger.c_str());
+ auto found = debugger_infos_.find(debugger);
+ if (found == debugger_infos_.end())
+ return;
+
+ debugger_info_ = found->second;
+ if (debugger == "ASAN")
+ setenv("TIZEN_ASAN_ACTIVATION", "1", 1);
+
+ ParseAndRedirectStandardFds(b);
+ RemoveFiles(debugger_info_->GetUnlinkList());
+
+ for (const auto& extra_env : debugger_info_->GetExtraEnvList())
+ ParseAndSetEnvironment(b, extra_env);
+
+ debug_argv_ = debugger_info_->GetDefaultOptList();
+ debug_argv_.insert(debug_argv_.begin(), debugger_info_->GetExe());
+ for (const auto& extra_key : debugger_info_->GetExtraKeyList())
+ ParseAndAddArgv(b, extra_key);
+
+ for (const auto& last_extra_key : debugger_info_->GetLastExtraKeyList())
+ ParseAndAddExtraArgv(b, last_extra_key);
+}
+
+void Debug::ChangeMountNamespace() {
+ auto target_pid = std::getenv("TARGET_PID");
+ if (target_pid == nullptr)
+ return;
+
+ std::string mnt_path = "/proc/" + std::string(target_pid) + "/ns/mnt";
+ int fd = open(mnt_path.c_str(), O_RDONLY);
+ if (fd < 0) {
+ _E("open() is failed. path(%s), errno(%d)", mnt_path.c_str(), errno);
+ return;
+ }
+
+ int ret = ::setns(fd, CLONE_NEWNS);
+ close(fd);
+ if (ret != 0) {
+ _E("setns() is failed. errno(%d)", errno);
+ return;
+ }
+
+ _D("setns() is successful");
+}
+
+void Debug::CheckWebAppDebugging(const tizen_base::Bundle& b) {
+ if (b.GetType(AUL_K_DEBUG) != BUNDLE_TYPE_NONE)
+ setenv("TIZEN_DEBUGGING_PORT", "1", 1);
+}
+
+bool Debug::CheckAsanApp(const std::string& appid) {
+ return asan_app_map_.find(appid) != asan_app_map_.end();
+}
+
+void Debug::CheckAndSetAsanActivation(const std::string& appid) {
+ if (CheckAsanApp(appid)) {
+ _W("Set TIZEN_ASAN_ACTIVATION. appid: %s", appid.c_str());
+ setenv("TIZEN_ASAN_ACTIVATION", "1", 1);
+ }
+}
+
+std::vector<std::string> Debug::GetExtraArgv() const {
+ return extra_argv_;
+}
+
+std::vector<std::string> Debug::GetArgv() const {
+ return debug_argv_;
+}
+
+bool Debug::ShouldAttach() const {
+ if (!debugger_info_)
+ return false;
+
+ return debugger_info_->GetAttachInfo() == "true";
+}
+
+Debug::~Debug() {
+ Dispose();
+}
+
+void Debug::Init() {
+ if (!disposed_)
+ return;
+
+ file_monitor_ = std::make_unique<FileMonitor>(kAsanAppListPath, this);
+ disposed_ = false;
+}
+
+void Debug::RemoveFiles(const std::vector<std::string>& files) {
+ for (const auto& file : files) {
+ if (fs::exists(file)) {
+ _D("[DEBUG] file: %s", file.c_str());
+ fs::remove(file);
+ }
+ }
+}
+
+void Debug::ParseAndSetEnvironment(const tizen_base::Bundle& b,
+ const std::string& key) {
+ _D("[DEBUG] key: %s", key.c_str());
+ std::vector<std::string> values = GetStringArray(b, key);
+ if (values.empty())
+ return;
+
+ std::string env;
+ for (const auto& value : values) {
+ if (!env.empty())
+ env += ",";
+
+ env += value;
+ }
+
+ const_cast<tizen_base::Bundle&>(b).Delete(key);
+ _D("[DEBUG] value: %s", env.c_str());
+ setenv(key.c_str(), env.c_str(), 1);
+}
+
+void Debug::ParseAndAddArgv(const tizen_base::Bundle& b,
+ const std::string& key) {
+ _D("[DEBUG] key: %s", key.c_str());
+ std::vector<std::string> values = GetStringArray(b, key);
+ if (values.empty())
+ return;
+
+ for (const auto& arg : values) {
+ debug_argv_.push_back(arg);
+ if (key == "__DLP_ATTACH_ARG__" && isdigit(arg[0])) {
+ _D("[DEBUG] TARGET_PID: %s", arg.c_str());
+ setenv("TARGET_PID", arg.c_str(), 1);
+ }
+ }
+
+ const_cast<tizen_base::Bundle&>(b).Delete(key);
+}
+
+void Debug::ParseAndAddExtraArgv(const tizen_base::Bundle& b,
+ const std::string& key) {
+ _D("[DEBUG] key: %s", key.c_str());
+ std::vector<std::string> values = GetStringArray(b, key);
+ if (values.empty()) return;
+
+ for (const auto& arg : values)
+ extra_argv_.push_back(arg);
+
+ const_cast<tizen_base::Bundle&>(b).Delete(key);
+}
+
+void Debug::ParseAndRedirectStandardFds(const tizen_base::Bundle& b) {
+ pid_t caller_pid = GetCallerPid(b);
+ if (caller_pid < 0)
+ return;
+
+ // stdin
+ std::string path = "/proc/" + std::to_string(caller_pid) + "/fd/";
+ int fd = open((path + std::to_string(STDIN_FILENO)).c_str(), O_RDONLY);
+ if (fd < 0) {
+ _E("Failed to open STDIN file descriptor. errno(%d)", errno);
+ return;
+ }
+
+ dup2(fd, STDIN_FILENO);
+ close(fd);
+
+ // stdout
+ fd = open((path + std::to_string(STDOUT_FILENO)).c_str(), O_WRONLY);
+ if (fd < 0) {
+ _E("Failed to open STDOUT file descriptor. errno(%d)", errno);
+ return;
+ }
+
+ dup2(fd, STDOUT_FILENO);
+ close(fd);
+
+ // stdout
+ fd = open((path + std::to_string(STDERR_FILENO)).c_str(), O_WRONLY);
+ if (fd < 0) {
+ _E("Failed to open STDERR file descriptor. errno(%d)", errno);
+ return;
+ }
+
+ dup2(fd, STDERR_FILENO);
+ close(fd);
+}
+
+pid_t Debug::GetCallerPid(const tizen_base::Bundle& b) {
+ auto pid_str = b.GetString(AUL_K_ORG_CALLER_PID);
+ if (pid_str.empty())
+ pid_str = b.GetString(AUL_K_CALLER_PID);
-AsanAppChecker::AsanAppChecker() : file_monitor_(kAsanAppListPath, this) {}
+ if (pid_str.empty())
+ return -1;
-void AsanAppChecker::Update() {
+ return std::stoi(pid_str);
+}
+
+void Debug::OnFileChanged(FileMonitor::FileMonitorEvent event) {
+ _W("%s was changed. event(%d)", kAsanAppListPath, static_cast<int>(event));
asan_app_map_.clear();
std::ifstream if_stream;
if_stream.open(kAsanAppListPath);
}
}
-bool AsanAppChecker::CheckAsanApp(const std::string& appid) const {
- return asan_app_map_.find(appid) != asan_app_map_.end();
-}
-
-void AsanAppChecker::OnFileChanged(
- launchpad::FileMonitor::FileMonitorEvent event) {
- _W("%s was changed. event(%d)", kAsanAppListPath, static_cast<int>(event));
- Update();
-}
-
} // namespace launchpad
* limitations under the License.
*/
-#ifndef DEBUG_HH_
-#define DEBUG_HH_
+#ifndef LAUNCHPAD_PROCESS_POOL_DEBUG_HH_
+#define LAUNCHPAD_PROCESS_POOL_DEBUG_HH_
+#include <bundle_cpp.h>
+
+#include <list>
+#include <memory>
#include <string>
+#include <unordered_map>
#include <unordered_set>
+#include <vector>
-#include <launchpad-process-pool/file_monitor.hh>
+#include "launchpad-process-pool/debugger_info.hh"
+#include "launchpad-process-pool/file_monitor.hh"
namespace launchpad {
-class AsanAppChecker : public launchpad::FileMonitor::IEvent {
+class Debug : public FileMonitor::IEvent {
public:
- AsanAppChecker();
- bool CheckAsanApp(const std::string& appid) const;
+ Debug(const Debug&) = delete;
+ Debug& operator = (const Debug&) = delete;
+ Debug(Debug&&) = delete;
+ Debug& operator = (Debug&&) = delete;
+
+ static Debug& GetInst();
+ void Init();
+ void Dispose();
+ void Load();
+ void PrepareDebugger(const tizen_base::Bundle& b);
+ std::vector<std::string> GetExtraArgv() const;
+ std::vector<std::string> GetArgv() const;
+ bool ShouldAttach() const;
+ bool CheckAsanApp(const std::string& appid);
+ void CheckAndSetAsanActivation(const std::string& appid);
+
+ static void ChangeMountNamespace();
+ static void CheckWebAppDebugging(const tizen_base::Bundle& b);
private:
- void Update();
+ Debug() = default;
+ ~Debug();
+
+ void RemoveFiles(const std::vector<std::string>& files);
+ void ParseAndSetEnvironment(
+ const tizen_base::Bundle& b, const std::string& key);
+ void ParseAndAddArgv(const tizen_base::Bundle& b, const std::string& key);
+ void ParseAndAddExtraArgv(const tizen_base::Bundle& b,
+ const std::string& key);
+ void ParseAndRedirectStandardFds(const tizen_base::Bundle& b);
+ pid_t GetCallerPid(const tizen_base::Bundle& b);
+
void OnFileChanged(launchpad::FileMonitor::FileMonitorEvent event) override;
+ private:
+ bool disposed_ = true;
+ DebuggerInfoPtr debugger_info_;
+ std::unordered_map<std::string, DebuggerInfoPtr> debugger_infos_;
+ std::vector<std::string> debug_argv_;
+ std::vector<std::string> extra_argv_;
std::unordered_set<std::string> asan_app_map_;
- static constexpr const char kAsanAppListPath[] =
- "/opt/usr/share/aul/debug/.asan_app_list";
- launchpad::FileMonitor file_monitor_;
+ std::unique_ptr<launchpad::FileMonitor> file_monitor_;
};
} // namespace launchpad
-#endif // DEBUG_HH_
+#endif // LAUNCHPAD_PROCESS_POOL_DEBUG_HH_
namespace fs = std::filesystem;
-void DebuggerInfoInflator::Parse(
- std::vector<DebuggerInfoPtr>& debugger_info_list,
- const fs::path& path) {
- std::ifstream fp;
- fp.open(path);
- if (fp.fail())
- return;
-
- DebuggerInfoPtr info;
- std::string input;
- while (std::getline(fp, input)) {
- std::istringstream ss(input);
- std::string tok1, tok2;
- if (!(ss >> tok1))
- continue;
-
- if (strcasecmp(kTagDebugger, tok1.c_str()) == 0) {
- if (info != nullptr) {
- _D("name: %s, exe: %s", info->name_.c_str(), info->exe_.c_str());
- debugger_info_list.push_back(std::move(info));
- }
-
- info = std::make_unique<DebuggerInfo>();
- continue;
- }
-
- if (!(ss >> tok2))
- continue;
- if (tok1.front() == '#' || info == nullptr)
- continue;
-
- std::string key;
- std::transform(tok1.begin(), tok1.end(), std::back_inserter(key),
- [](char ch) { return toupper(ch); });
- if (kTagName == key) {
- info->name_ = std::move(tok2);
- } else if (kTagExe == key) {
- fs::path file(tok2);
- if (fs::exists(file) == false) {
- _E("Failed to access %s", tok2.c_str());
- info.reset();
- continue;
- }
-
- info->exe_ = std::move(tok2);
- } else if (kTagAppType == key) {
- std::string line = std::move(tok2);
- do {
- auto tokens = Split(line, " |\t\r\n");
- for (auto& token : tokens) {
- _E("types: %s", token.c_str());
- info->app_types_.push_back(std::move(token));
- }
- } while (std::getline(ss, line));
- } else if (kTagExtraKey == key) {
- info->extra_key_list_.push_back(std::move(tok2));
- } else if (kTagExtraEnv == key) {
- info->extra_env_list_.push_back(std::move(tok2));
- } else if (kTagUnlink == key) {
- info->unlink_list_.push_back(std::move(tok2));
- } else if (kTagAttach == key) {
- info->attach_ = std::move(tok2);
- } else if (kTagLastExtraKey == key) {
- info->last_extra_key_list_.push_back(std::move(tok2));
- } else if (kTagDefaultOpt == key) {
- info->default_opt_list_.push_back(std::move(tok2));
- }
- }
-
- fp.close();
- if (info) {
- _D("name: %s, exe: %s", info->name_.c_str(), info->exe_.c_str());
- debugger_info_list.push_back(std::move(info));
- }
-}
-
const std::string& DebuggerInfo::GetName() const {
return name_;
}
return default_opt_list_;
}
-std::vector<DebuggerInfoPtr> DebuggerInfoInflator::Inflate(
+std::unordered_map <std::string, DebuggerInfoPtr> DebuggerInfoInflator::Inflate(
const std::string_view path) {
- fs::path p(path);
- if (fs::is_directory(p) == false)
- return {};
+ fs::path input_path(path);
+ if (fs::is_directory(input_path) == false)
+ return debugger_infos_;
- std::vector<DebuggerInfoPtr> result;
- for (auto& entry : fs::directory_iterator(p)) {
+ for (auto& entry : fs::directory_iterator(input_path)) {
fs::path file(entry.path());
if (file.extension() == ".debugger")
- Parse(result, file);
+ Parse(file);
+ }
+
+ return debugger_infos_;
+}
+
+void DebuggerInfoInflator::Parse(const fs::path& path) {
+ std::ifstream input_file(path);
+ if (!input_file.is_open())
+ return;
+
+ DebuggerInfoPtr current_info;
+ std::string input;
+ while (std::getline(input_file, input)) {
+ std::istringstream ss(input);
+ std::string token1;
+ if (!(ss >> token1))
+ continue;
+
+ std::string key = ToUpper(token1);
+ if (key == kTagDebugger) {
+ if (current_info != nullptr)
+ InsertDebuggerInfo(std::move(current_info));
+
+ current_info = std::make_unique<DebuggerInfo>();
+ continue;
+ }
+
+ if (key.front() == '#' || current_info == nullptr)
+ continue;
+
+ std::string token2;
+ if (!(ss >> token2))
+ continue;
+
+ if (key == kTagName) {
+ current_info->name_ = std::move(token2);
+ } else if (key == kTagExe) {
+ current_info->exe_ = std::move(token2);
+ } else if (key == kTagAppType) {
+ ParseAndSetAppTypes(current_info.get(), ss, std::move(token2));
+ } else if (key == kTagExtraKey) {
+ current_info->extra_key_list_.push_back(std::move(token2));
+ } else if (key == kTagExtraEnv) {
+ current_info->extra_env_list_.push_back(std::move(token2));
+ } else if (key == kTagUnlink) {
+ current_info->unlink_list_.push_back(std::move(token2));
+ } else if (key == kTagAttach) {
+ current_info->attach_ = std::move(token2);
+ } else if (key == kTagLastExtraKey) {
+ current_info->last_extra_key_list_.push_back(std::move(token2));
+ } else if (key == kTagDefaultOpt) {
+ current_info->default_opt_list_.push_back(std::move(token2));
+ }
}
- return result;
+ if (current_info != nullptr)
+ InsertDebuggerInfo(std::move(current_info));
+
+ input_file.close();
+}
+
+void DebuggerInfoInflator::ParseAndSetAppTypes(DebuggerInfo* info,
+ std::istringstream& ss, std::string line) {
+ do {
+ auto tokens = Split(line, " |\t\r\n");
+ for (auto& token : tokens) {
+ _D("app-type: %s", token.c_str());
+ info->app_types_.push_back(std::move(token));
+ }
+ } while (std::getline(ss, line));
+}
+
+void DebuggerInfoInflator::InsertDebuggerInfo(DebuggerInfoPtr info) {
+ if (debugger_infos_.find(info->name_) != debugger_infos_.end())
+ return;
+
+ _D("name: %s, exe: %s", info->name_.c_str(), info->exe_.c_str());
+ std::string name = info->name_;
+ debugger_infos_[std::move(name)] = std::move(info);
}
} // namespace launchpad
* limitations under the License.
*/
-#ifndef DEBUGGER_INFO_HH_
-#define DEBUGGER_INFO_HH_
+#ifndef LAUNCHPAD_PROCESS_POOL_DEBUGGER_INFO_HH_
+#define LAUNCHPAD_PROCESS_POOL_DEBUGGER_INFO_HH_
#include <filesystem>
#include <memory>
#include <string>
#include <string_view>
+#include <unordered_map>
#include <vector>
namespace launchpad {
class DebuggerInfoInflator {
public:
- std::vector<DebuggerInfoPtr> Inflate(const std::string_view path);
+ std::unordered_map<std::string, DebuggerInfoPtr> Inflate(
+ const std::string_view path);
+
+ private:
+ void Parse(const std::filesystem::path& path);
+ void ParseAndSetAppTypes(DebuggerInfo* info, std::istringstream& ss,
+ std::string line);
+ void InsertDebuggerInfo(DebuggerInfoPtr info);
+
private:
- void Parse(std::vector<DebuggerInfoPtr>& debugger_info_list,
- const std::filesystem::path& path);
+ std::unordered_map<std::string, DebuggerInfoPtr> debugger_infos_;
};
} // namespace launchpad
-#endif // DEBUGGER_INFO_HH_
+#endif // LAUNCHPAD_PROCESS_POOL_DEBUGGER_INFO_HH_
#include <procfs.hh>
-#include "launchpad-process-pool/debug.hh"
#include "launchpad-process-pool/launcher_info.hh"
#include "launchpad-process-pool/launchpad_config.h"
-#include "launchpad-process-pool/launchpad_debug.h"
#include "launchpad-process-pool/launchpad_inotify.h"
#include "launchpad-process-pool/launchpad_io_channel.h"
-#include "launchpad-process-pool/loader_info.hh"
#include "launchpad-process-pool/slot_info.h"
#include "lib/common/inc/key.h"
#include "lib/common/inc/launchpad_common.h"
#include "lib/common/inc/launchpad_types.h"
#include "lib/common/inc/perf.h"
+#include "launchpad-process-pool/debug.hh"
#include "launchpad-process-pool/dbus.hh"
+#include "launchpad-process-pool/loader_info.hh"
#include "launchpad-process-pool/log.hh"
#include "launchpad-process-pool/memory_monitor.hh"
#include "launchpad-process-pool/signal_manager.hh"
io_channel_h __label_monitor_channel;
io_channel_h __launchpad_channel;
int __client_fd = -1;
-launchpad::AsanAppChecker __asan_app_checker;
std::unique_ptr<launchpad::Worker> cleaner;
SigchldHandler sigchld_handler;
return 0;
}
-static int __create_launcher_argv(int* argc, char*** argv,
- const char* app_type) {
- int launcher_argc;
- char** launcher_argv;
- launchpad::LauncherInfoPtr launcher_info;
- const char* exe;
- int i;
-
- auto it = std::find_if(
- launcher_info_list.begin(), launcher_info_list.end(),
+static std::vector<std::string> GetLauncherArgv(
+ const std::string& app_type) {
+ std::vector<std::string> argv;
+ auto found = std::find_if(launcher_info_list.begin(),
+ launcher_info_list.end(),
[app_type](const launchpad::LauncherInfoPtr& info) -> bool {
return std::find_if(info->GetAppTypes().begin(),
- info->GetAppTypes().end(),
- [app_type](const std::string& type) -> bool {
- return strcmp(type.c_str(), app_type) == 0;
- }) != info->GetAppTypes().end();
+ info->GetAppTypes().end(),
+ [app_type](const std::string& type) -> bool {
+ return type == app_type;
+ }) != info->GetAppTypes().end();
});
+ if (found == launcher_info_list.end())
+ return argv;
- if (it == launcher_info_list.end())
- return 0;
-
- launcher_info = *it;
- exe = launcher_info->GetExe().c_str();
-
- auto& extra_args = launcher_info->GetExtraArgs();
- launcher_argc = extra_args.size() + 1;
- launcher_argv = static_cast<char**>(calloc(launcher_argc, sizeof(char*)));
- if (launcher_argv == nullptr) {
- _E("out of memory");
- return -1;
- }
-
- i = LOADER_ARG_PATH;
- launcher_argv[i++] = strdup(exe);
-
- for (auto& extra_arg : extra_args) {
- launcher_argv[i++] = strdup(extra_arg.c_str());
- }
-
- *argc = launcher_argc;
- *argv = launcher_argv;
-
- return 0;
-}
-
-static void __destroy_launcher_argv(int argc, char** argv) {
- int i;
-
- if (argv == nullptr)
- return;
-
- for (i = 0; i < argc; i++)
- free(argv[i]);
- free(argv);
+ auto launcher_info = *found;
+ argv.insert(argv.end(), launcher_info->GetExe());
+ argv.insert(argv.end(), launcher_info->GetExtraArgs().begin(),
+ launcher_info->GetExtraArgs().end());
+ return argv;
}
-static int __create_app_argv(int* argc, char*** argv, const char* app_path,
- bundle* kb, const char* app_type) {
- int new_argc;
- char** new_argv;
- bool attach = false;
- struct app_arg debug_arg = { 0, };
- struct app_arg launcher_arg = { 0, };
- struct app_arg arg = { 0, };
- struct app_arg debug_extra_arg = { 0, };
- int ret;
- int i;
- int c;
-
- ret = _debug_create_argv(&debug_arg.argc, &debug_arg.argv, &attach);
- if (ret < 0) {
- _E("Failed to create debugger argv");
- return -1;
- }
-
- if (attach) {
- *argc = debug_arg.argc;
- *argv = debug_arg.argv;
- return 0;
- }
+static std::vector<std::string> CreateAppArgv(const std::string& app_path,
+ const tizen_base::Bundle& b, const std::string& app_type) {
+ auto& inst = launchpad::Debug::GetInst();
+ std::vector<std::string> argv = inst.GetArgv();
+ if (inst.ShouldAttach())
+ return argv;
- ret = _debug_create_extra_argv(&debug_extra_arg.argc, &debug_extra_arg.argv);
- if (ret < 0) {
- _E("Failed to create debugger extra argv");
- _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
- return -1;
- }
+ auto launcher_argv = GetLauncherArgv(app_type);
+ if (!launcher_argv.empty())
+ argv.insert(argv.end(), launcher_argv.begin(), launcher_argv.end());
- ret =
- __create_launcher_argv(&launcher_arg.argc, &launcher_arg.argv, app_type);
- if (ret < 0) {
- _E("Failed to create launcher argv");
- _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
- _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
- return -1;
- }
+ auto exported_argv = b.Export();
+ exported_argv[LOADER_ARG_PATH] = app_path;
+ if (!exported_argv.empty())
+ argv.insert(argv.end(), exported_argv.begin(), exported_argv.end());
- arg.argc = bundle_export_to_argv(kb, &arg.argv);
- if (arg.argc <= 0) {
- _E("Failed to export bundle");
- __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
- _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
- _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
- return -1;
- }
- arg.argv[LOADER_ARG_PATH] = strdup(app_path);
-
- new_argc =
- debug_arg.argc + launcher_arg.argc + arg.argc + debug_extra_arg.argc;
- if (new_argc == arg.argc) {
- *argc = arg.argc;
- *argv = arg.argv;
- return 0;
- }
+ auto extra_argv = inst.GetExtraArgv();
+ if (!extra_argv.empty())
+ argv.insert(argv.end(), extra_argv.begin(), extra_argv.end());
- new_argv = reinterpret_cast<char**>(calloc(new_argc + 1, sizeof(char*)));
- if (new_argv == nullptr) {
- _E("out of memory");
- free(arg.argv[LOADER_ARG_PATH]);
- bundle_free_exported_argv(arg.argc, &arg.argv);
- __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
- _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv);
- _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
- return -1;
- }
-
- c = static_cast<int>(LOADER_ARG_PATH);
- for (i = 0; i < debug_arg.argc; i++)
- new_argv[c++] = debug_arg.argv[i];
- for (i = 0; i < launcher_arg.argc; i++)
- new_argv[c++] = launcher_arg.argv[i];
- for (i = 0; i < arg.argc; i++)
- new_argv[c++] = arg.argv[i];
- for (i = 0; i < debug_extra_arg.argc; i++)
- new_argv[c++] = debug_extra_arg.argv[i];
-
- *argc = new_argc;
- *argv = new_argv;
-
- return 0;
+ return argv;
}
static void __real_launch(const char* app_path, bundle* kb,
appinfo_t* menu_info) {
- int app_argc = 0;
- char** app_argv;
- int i;
- int ret;
-
- if (bundle_get_val(kb, AUL_K_DEBUG) != nullptr)
- setenv("TIZEN_DEBUGGING_PORT", "1", 1);
+ tizen_base::Bundle b(kb, false, false);
+ launchpad::Debug::CheckWebAppDebugging(b);
- ret = __create_app_argv(&app_argc, &app_argv, app_path, kb,
- menu_info->app_type);
- if (ret < 0) {
- _E("Failed to create app argv");
+ std::vector<std::string> argv = CreateAppArgv(app_path, b,
+ menu_info->app_type);
+ char** app_argv = static_cast<char**>(calloc(argv.size() + 1, sizeof(char*)));
+ if (app_argv == nullptr) {
+ _E("Out of memory");
exit(-1);
}
- for (i = 0; i < app_argc; i++)
+ int app_argc = argv.size();
+ for (int i = 0; i < app_argc; i++) {
+ app_argv[i] = const_cast<char*>(argv[i].c_str());
SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
+ }
PERF("setup argument done");
__normal_fork_exec(app_argc, app_argv, app_path);
+ free(app_argv);
}
static int __prepare_exec(const char* appid, const char* app_path,
return PAD_ERR_FAILED;
if (bundle_get_type(kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
- _debug_change_mount_namespace();
+ launchpad::Debug::ChangeMountNamespace();
/* SET PRIVILEGES*/
enabled_light_user = bundle_get_val(kb, AUL_K_ENABLED_LIGHT_USER);
PERF("fork done");
_D("lock up test log(no error) : fork done");
- if (bundle_get_type(launch_arg->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
- _debug_prepare_debugger(launch_arg->kb);
+ tizen_base::Bundle b(launch_arg->kb, false, false);
+ if (b.GetType(AUL_K_SDK) != BUNDLE_TYPE_NONE)
+ launchpad::Debug::GetInst().PrepareDebugger(b);
- if (__asan_app_checker.CheckAsanApp(launch_arg->appid)) {
- _W("%s TIZEN_ASAN_ACTIVATION", launch_arg->appid);
- setenv("TIZEN_ASAN_ACTIVATION", "1", 1);
- }
+ launchpad::Debug::GetInst().CheckAndSetAsanActivation(launch_arg->appid);
launchpad::SignalManager::GetInst().UnblockSigchld();
_delete_sock_path(getpid(), getuid());
static void __fork_processing(request_h request) {
if (bundle_get_type(request->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
- _debug_init();
+ launchpad::Debug::GetInst().Load();
_W("appid: %s", request->menu_info->appid);
request->pid = __launch_directly(request->menu_info->appid, request->app_path,
static int __launch_request_do(request_h request) {
if (request->loader_id == PAD_LOADER_ID_DIRECT || request->cpc == nullptr ||
- __asan_app_checker.CheckAsanApp(request->menu_info->appid)) {
+ launchpad::Debug::GetInst().CheckAsanApp(request->menu_info->appid)) {
__fork_processing(request);
return 0;
}
launchpad::LauncherInfoInflator inflator;
launcher_info_list = inflator.Inflate(LAUNCHER_INFO_PATH);
+ launchpad::Debug::GetInst().Init();
+
__add_app_defined_loaders();
ret = _send_cmd_to_amd(LAUNCHPAD_LAUNCH_SIGNAL);
if (_send_cmd_to_amd(LAUNCHPAD_DEAD_SIGNAL) < 0)
_W("Failed to send cmd(%d) to amd", LAUNCHPAD_DEAD_SIGNAL);
- _debug_fini();
+ launchpad::Debug::GetInst().Dispose();
launcher_info_list.clear();
_config_fini();
_inotify_fini();
+++ /dev/null
-/*
- * 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 "launchpad-process-pool/launchpad_debug.h"
-
-#include <bundle_internal.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <linux/limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <algorithm>
-
-#include "launchpad-process-pool/debugger_info.hh"
-#include "lib/common/inc/key.h"
-#include "lib/common/inc/launchpad_common.h"
-#include "lib/common/inc/launchpad_types.h"
-
-#define DEBUGGER_INFO_PATH "/usr/share/aul"
-
-namespace {
-
-int __debug_initialized;
-std::vector<launchpad::DebuggerInfoPtr> __debugger_info_list;
-launchpad::DebuggerInfoPtr __debugger_info;
-std::vector<std::string> __debug_argv_list;
-std::vector<std::string> __extra_argv_list;
-
-} // namespace
-
-int _debug_change_mount_namespace(void) {
- const char* pid_str;
- char buf[PATH_MAX];
- int ret;
- int fd;
-
- pid_str = getenv("TARGET_PID");
- if (pid_str == nullptr)
- return 0;
-
- snprintf(buf, sizeof(buf), "/proc/%s/ns/mnt", pid_str);
- fd = open(buf, O_RDONLY);
- if (fd < 0) {
- _E("open() is failed. path(%s), errno(%d)", buf, errno);
- return -1;
- }
-
- ret = setns(fd, CLONE_NEWNS);
- close(fd);
- if (ret != 0)
- _E("setns() is failed. errno(%d)", errno);
-
- return ret;
-}
-
-int _debug_create_extra_argv(int* argc, char*** argv) {
- int new_argc;
- char** new_argv;
- int i;
-
- if (argc == nullptr || argv == nullptr) {
- _E("[DEBUG] Invalid parameter");
- return -1;
- }
-
- if (__debugger_info == nullptr)
- return 0;
-
- new_argc = __extra_argv_list.size();
- if (new_argc == 0)
- return 0;
-
- new_argv = static_cast<char**>(calloc(new_argc, sizeof(char*)));
- if (new_argv == nullptr) {
- _E("out of memory");
- return -1;
- }
-
- i = LOADER_ARG_PATH;
- for (auto& argv : __extra_argv_list) {
- new_argv[i++] = strdup(argv.c_str());
- }
-
- *argc = new_argc;
- *argv = new_argv;
- _D("[DEBUG] argc: %d, i: %d", *argc, i);
-
- return 0;
-}
-
-int _debug_create_argv(int* argc, char*** argv, bool* attach) {
- int new_argc = 0;
- char** new_argv;
- const char* exe;
- const char* attach_str;
- int i;
-
- if (argc == nullptr || argv == nullptr || attach == nullptr) {
- _E("[DEBUG] Invalid parameter");
- return -1;
- }
-
- if (__debugger_info == nullptr)
- return 0;
-
- exe = __debugger_info->GetExe().data();
- if (exe == nullptr)
- return 0;
-
- attach_str = __debugger_info->GetAttachInfo().c_str();
- if (attach_str && strcasecmp(attach_str, "true") == 0) {
- *attach = true;
- new_argc++;
- }
-
- auto list = __debugger_info->GetDefaultOptList();
- new_argc += __debug_argv_list.size() + list.size() + 1;
- new_argv = static_cast<char**>(calloc(new_argc, sizeof(char*)));
- if (new_argv == nullptr) {
- _E("out of memory");
- return -1;
- }
-
- i = LOADER_ARG_PATH;
- new_argv[i++] = strdup(exe);
-
- for (auto& debug_argv : list) {
- new_argv[i++] = strdup(debug_argv.c_str());
- }
-
- for (auto& debug_argv : __debug_argv_list) {
- new_argv[i++] = strdup(debug_argv.c_str());
- }
-
- *argc = new_argc;
- *argv = new_argv;
- _D("[DEBUG] argc: %d, argv[0]: %s", new_argc, new_argv[LOADER_ARG_PATH]);
-
- return 0;
-}
-
-void _debug_destroy_argv(int argc, char** argv) {
- int i;
-
- if (argv == nullptr)
- return;
-
- for (i = 0; i < argc; i++)
- free(argv[i]);
- free(argv);
-}
-
-int _debug_get_caller_pid(bundle* kb) {
- const char* pid_str;
- int pid;
-
- pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
- if (pid_str == nullptr)
- pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
-
- if (pid_str == nullptr)
- return -1;
-
- pid = atoi(pid_str);
- if (pid <= 1)
- return -1;
-
- return pid;
-}
-
-static int __redirect_std_fds(bundle* kb) {
- char path[PATH_MAX];
- char err_buf[1024];
- int fd;
- int caller_pid;
-
- if (kb == nullptr) {
- _E("[DEBUG] Invalid parameter");
- return -1;
- }
-
- caller_pid = _debug_get_caller_pid(kb);
- if (caller_pid < 0) {
- _E("[DEBUG] Failed to get caller pid");
- return -1;
- }
-
- /* stdin */
- snprintf(path, sizeof(path), "/proc/%d/fd/0", caller_pid);
- fd = open(path, O_RDONLY);
- if (fd < 0) {
- _E("[DEBUG] Failed to open %s [%s]", path,
- strerror_r(errno, err_buf, sizeof(err_buf)));
- return -1;
- }
- dup2(fd, 0);
- close(fd);
-
- /* stdout */
- snprintf(path, sizeof(path), "/proc/%d/fd/1", caller_pid);
- fd = open(path, O_WRONLY);
- if (fd < 0) {
- _E("[DEBUG] Failed to open %s [%s]", path,
- strerror_r(errno, err_buf, sizeof(err_buf)));
- return -1;
- }
- dup2(fd, 1);
- close(fd);
-
- /* stderr */
- snprintf(path, sizeof(path), "/proc/%d/fd/2", caller_pid);
- fd = open(path, O_WRONLY);
- if (fd < 0) {
- _E("[DEBUG] Failed to open %s [%s]", path,
- strerror_r(errno, err_buf, sizeof(err_buf)));
- return -1;
- }
- dup2(fd, 2);
- close(fd);
-
- return 0;
-}
-
-static void __add_extra_argv(const std::string& key, bundle* kb) {
- const char* str;
- const char** str_arr = nullptr;
- int len = 0;
- int i;
-
- _D("[DEBUG] key: %s", key.c_str());
- if (bundle_get_type(kb, key.c_str()) & BUNDLE_TYPE_ARRAY) {
- str_arr = bundle_get_str_array(kb, key.c_str(), &len);
- } else {
- str = bundle_get_val(kb, key.c_str());
- if (str) {
- str_arr = &str;
- len = 1;
- }
- }
-
- for (i = 0; i < len; i++) {
- if (str_arr[i] == nullptr)
- break;
-
- __extra_argv_list.push_back(str_arr[i]);
- }
-
- if (str_arr)
- bundle_del(kb, key.c_str());
-}
-
-static void __add_debug_argv(const std::string& key, bundle* kb) {
- const char* str;
- const char** str_arr = nullptr;
- int len = 0;
- int i;
-
- _D("[DEBUG] key: %s", key.c_str());
- if (bundle_get_type(kb, key.c_str()) & BUNDLE_TYPE_ARRAY) {
- str_arr = bundle_get_str_array(kb, key.c_str(), &len);
- } else {
- str = bundle_get_val(kb, key.c_str());
- if (str) {
- str_arr = &str;
- len = 1;
- }
- }
-
- for (i = 0; i < len; i++) {
- if (str_arr[i] == nullptr)
- break;
-
- __debug_argv_list.push_back(str_arr[i]);
- if (!strcmp(key.c_str(), "__DLP_ATTACH_ARG__")) {
- if (isdigit(str_arr[i][0])) {
- _D("Target PID: %s", str_arr[i]);
- setenv("TARGET_PID", str_arr[i], 1);
- }
- }
- }
-
- if (str_arr)
- bundle_del(kb, key.c_str());
-}
-
-static void __set_debug_env(const std::string& key, bundle* kb) {
- const char* str;
- const char** str_arr = nullptr;
- int len = 0;
- int i;
- char buf[LINE_MAX] = {
- 0,
- };
-
- _D("[DEBUG] key: %s", key.c_str());
- if (bundle_get_type(kb, key.c_str()) & BUNDLE_TYPE_ARRAY) {
- str_arr = bundle_get_str_array(kb, key.c_str(), &len);
- } else {
- str = bundle_get_val(kb, key.c_str());
- if (str) {
- str_arr = &str;
- len = 1;
- }
- }
-
- if (str_arr == nullptr)
- return;
-
- strncat(buf, str_arr[0], sizeof(buf) - strlen(buf) - 1);
- for (i = 1; i < len; i++) {
- if (str_arr[i] == nullptr)
- break;
-
- strncat(buf, ",", sizeof(buf) - strlen(buf) - 1);
- strncat(buf, str_arr[i], sizeof(buf) - strlen(buf) - 1);
- }
-
- bundle_del(kb, key.c_str());
- _D("[DEBUG] name: %s, value: %s", key.c_str(), buf);
- setenv(key.c_str(), buf, 1);
-}
-
-static void __remove_file(const std::string& file) {
- _D("[DEBUG] file: %s", file.c_str());
- if (access(file.c_str(), F_OK) == 0) {
- if (remove(file.c_str()) != 0)
- _W("[DEBUG] Failed to remove %s", file.c_str());
- }
-}
-
-void _debug_prepare_debugger(bundle* kb) {
- const char* debugger;
- int ret;
-
- if (kb == nullptr)
- return;
-
- debugger = bundle_get_val(kb, AUL_K_SDK);
- if (debugger == nullptr)
- return;
-
- if (!strcmp(debugger, "ASAN"))
- setenv("TIZEN_ASAN_ACTIVATION", "1", 1);
-
- ret = __redirect_std_fds(kb);
- if (ret < 0)
- _E("[DEBUG] Failed to redirect standard fds");
-
- _D("[DEBUG] debugger: %s", debugger);
- auto it =
- std::find_if(__debugger_info_list.begin(), __debugger_info_list.end(),
- [&](const launchpad::DebuggerInfoPtr& info) -> bool {
- return strcasecmp(info->GetExe().c_str(), debugger) == 0;
- });
- if (it == __debugger_info_list.end())
- return;
-
- __debugger_info = *it;
- for (auto& unlink_file : __debugger_info->GetUnlinkList()) {
- __remove_file(unlink_file);
- }
-
- for (auto& extra_env : __debugger_info->GetExtraEnvList()) {
- __set_debug_env(extra_env, kb);
- }
-
- for (auto& extra_key : __debugger_info->GetExtraKeyList()) {
- __add_debug_argv(extra_key, kb);
- }
-
- for (auto& last_extra_key : __debugger_info->GetLastExtraKeyList()) {
- __add_extra_argv(last_extra_key, kb);
- }
-}
-
-int _debug_init(void) {
- if (__debug_initialized)
- return 0;
-
- launchpad::DebuggerInfoInflator inflator;
- __debugger_info_list = inflator.Inflate(DEBUGGER_INFO_PATH);
- if (__debugger_info_list.empty())
- return -1;
-
- __debug_initialized = 1;
-
- return 0;
-}
-
-void _debug_fini(void) {
- if (!__debug_initialized)
- return;
-
- __debugger_info_list.clear();
-}
+++ /dev/null
-/*
- * 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 __LAUNCHPAD_DEBUG_H__
-#define __LAUNCHPAD_DEBUG_H__
-
-#include <stdbool.h>
-#include <bundle.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int _debug_change_mount_namespace(void);
-int _debug_create_extra_argv(int *arg, char ***argv);
-int _debug_create_argv(int *argc, char ***argv, bool *attach);
-void _debug_destroy_argv(int argc, char **argv);
-int _debug_get_caller_pid(bundle *kb);
-void _debug_prepare_debugger(bundle *kb);
-int _debug_init(void);
-void _debug_fini(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __LAUNCHPAD_DEBUG_H__ */
* limitations under the License.
*/
-#include "util.hh"
+#include "launchpad-process-pool/util.hh"
+#include <algorithm>
+#include <cctype>
#include <regex>
+#include <utility>
namespace launchpad {
std::vector<std::string> Split(const std::string& str,
- const std::string& delim) {
+ const std::string& delim) {
const std::regex deli("[^" + delim + "]+");
std::vector<std::string> result;
for (auto i = std::sregex_iterator(str.begin(), str.end(), deli);
- i != std::sregex_iterator(); ++i) {
+ i != std::sregex_iterator(); ++i)
result.push_back((*i).str());
- }
return result;
}
+std::string ToUpper(std::string str) {
+ std::string result = std::move(str);
+ std::transform(result.begin(), result.end(), result.begin(), ::toupper);
+ return result;
+}
+
} // namespace launchpad
* limitations under the License.
*/
-#ifndef UTIL_HH_
-#define UTIL_HH_
+#ifndef LAUNCHPAD_PROCESS_POOL_UTIL_HH_
+#define LAUNCHPAD_PROCESS_POOL_UTIL_HH_
#include <string>
#include <vector>
}
std::vector<std::string> Split(const std::string& str,
- const std::string& delim);
+ const std::string& delim);
+
+std::string ToUpper(std::string str);
} // namespace launchpad
-#endif // UTIL_HH_
+#endif // LAUNCHPAD_PROCESS_POOL_UTIL_HH_
TEST_F(LaunchpadTest, DebuggerInfoTest) {
DebuggerInfoInflator inflator;
- auto list = inflator.Inflate(".");
- EXPECT_EQ(list.size(), 1);
- auto info = std::move(list.front());
+ auto map = inflator.Inflate(".");
+ EXPECT_EQ(map.size(), 1);
+ auto info = std::move(map["DEBUG"]);
EXPECT_EQ(info->GetName(), "DEBUG");
EXPECT_EQ(info->GetExe(), "test_debugger");
EXPECT_EQ(info->GetAppTypes().size(), 2);