The launchpad dbus is implemented using C++ language.
Change-Id: I6aea493bf48a51cfdeb54da88e83732e9348ae2c
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
PKG_CHECK_MODULES(DBUS_DEPS REQUIRED dbus-1)
PKG_CHECK_MODULES(DLOG_DEPS REQUIRED dlog)
PKG_CHECK_MODULES(DLOG_REDIRECT_STDOUT_DEPS REQUIRED dlog-redirect-stdout)
-PKG_CHECK_MODULES(ECORE_DEPS REQUIRED ecore)
PKG_CHECK_MODULES(ECORE_CORE_DEPS REQUIRED ecore-core)
+PKG_CHECK_MODULES(ECORE_DEPS REQUIRED ecore)
PKG_CHECK_MODULES(ELEMENTARY_DEPS REQUIRED elementary)
PKG_CHECK_MODULES(GIO_DEPS REQUIRED gio-2.0)
+PKG_CHECK_MODULES(GMOCK_DEPS REQUIRED gmock)
PKG_CHECK_MODULES(INIPARSER_DEPS REQUIRED iniparser)
PKG_CHECK_MODULES(LIBCAP_DEPS REQUIRED libcap)
PKG_CHECK_MODULES(LIBSMACK_DEPS REQUIRED libsmack)
PKG_CHECK_MODULES(PKGMGR_INSTALLER_DEPS REQUIRED pkgmgr-installer)
PKG_CHECK_MODULES(SECURITY_MANAGER_DEPS REQUIRED security-manager)
PKG_CHECK_MODULES(TANCHOR_DEPS REQUIRED tanchor)
+PKG_CHECK_MODULES(TIZEN_SHARED_QUEUE_DEPS REQUIRED tizen-shared-queue)
PKG_CHECK_MODULES(TTRACE_DEPS REQUIRED ttrace)
PKG_CHECK_MODULES(VCONF_DEPS REQUIRED vconf)
-PKG_CHECK_MODULES(GMOCK_DEPS REQUIRED gmock)
ENABLE_TESTING()
ADD_TEST(NAME ${TARGET_LAUNCHPAD_PROCESS_POOL_UNITTEST}
Source1004: app-defined-loader.manifest
BuildRequires: cmake
+BuildRequires: pkgconfig(aul)
BuildRequires: pkgconfig(bundle)
-BuildRequires: pkgconfig(gio-2.0)
-BuildRequires: pkgconfig(ecore)
+BuildRequires: pkgconfig(buxton2)
+BuildRequires: pkgconfig(dbus-1)
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(dlog-redirect-stdout)
-BuildRequires: pkgconfig(libsystemd)
+BuildRequires: pkgconfig(ecore)
BuildRequires: pkgconfig(elementary)
-BuildRequires: pkgconfig(vconf)
-BuildRequires: pkgconfig(buxton2)
-BuildRequires: pkgconfig(security-manager)
-BuildRequires: pkgconfig(aul)
-BuildRequires: pkgconfig(ttrace)
-BuildRequires: pkgconfig(libtzplatform-config)
-BuildRequires: pkgconfig(libcap)
-BuildRequires: pkgconfig(tanchor)
-BuildRequires: pkgconfig(dbus-1)
+BuildRequires: pkgconfig(gio-2.0)
+BuildRequires: pkgconfig(gmock)
BuildRequires: pkgconfig(iniparser)
-BuildRequires: pkgconfig(libxml-2.0)
+BuildRequires: pkgconfig(libcap)
BuildRequires: pkgconfig(libsmack)
+BuildRequires: pkgconfig(libsystemd)
+BuildRequires: pkgconfig(libtzplatform-config)
+BuildRequires: pkgconfig(libxml-2.0)
BuildRequires: pkgconfig(pkgmgr-installer)
-BuildRequires: pkgconfig(gmock)
+BuildRequires: pkgconfig(security-manager)
+BuildRequires: pkgconfig(tanchor)
+BuildRequires: pkgconfig(tizen-shared-queue)
+BuildRequires: pkgconfig(ttrace)
+BuildRequires: pkgconfig(vconf)
Requires(post): /sbin/ldconfig
Requires(post): /usr/bin/systemctl
LIBTZPLATFORM_CONFIG_DEPS
SECURITY_MANAGER_DEPS
TANCHOR_DEPS
+ TIZEN_SHARED_QUEUE_DEPS
TTRACE_DEPS
VCONF_DEPS
)
TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD_PROCESS_POOL} PUBLIC
- ${TARGET_LAUNCHPAD_COMMON} "-lm -ldl")
+ ${TARGET_LAUNCHPAD_COMMON} "-lm -ldl -lpthread")
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/packaging/default.debugger.in
${CMAKE_SOURCE_DIR}/packaging/default.debugger @ONLY)
--- /dev/null
+/*
+ * Copyright (c) 2023 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/dbus.hh"
+
+#include <gio/gio.h>
+#include <glib.h>
+
+#include <chrono>
+#include <memory>
+#include <thread>
+#include <utility>
+
+#include <shared-queue.hpp>
+
+#include "launchpad-process-pool/log_private.hh"
+
+namespace launchpad {
+namespace {
+
+constexpr const uint32_t ERROR_THRESHOLD = 10;
+constexpr const uint32_t ERROR_MODULO = 1000;
+constexpr const uint32_t PENDING_ITEM_INTERVAL = 1000;
+constexpr const char AUL_DBUS_PATH[] = "/aul/dbus_handler";
+constexpr const char AUL_DBUS_SIGNAL_INTERFACE[] = "org.tizen.aul.signal";
+constexpr const char AUL_DBUS_APPDEAD_SIGNAL[] = "app_dead";
+constexpr const char AUL_DBUS_APPLAUNCH_SIGNAL[] = "app_launch";
+
+class DBusMessage {
+ public:
+ DBusMessage(std::string path, std::string interface, std::string signal_name,
+ GVariant *param, std::string log_message)
+ : path_(std::move(path)), interface_(std::move(interface)),
+ signal_name_(std::move(signal_name)), param_(param),
+ log_message_(std::move(log_message)) {}
+
+ explicit DBusMessage(bool done) : done_(done) {}
+
+ ~DBusMessage() {
+ if (param_ != nullptr)
+ g_variant_unref(param_);
+ }
+
+ const std::string& GetPath() const { return path_; }
+
+ const std::string& GetInterface() const { return interface_; }
+
+ const std::string& GetSignalName() const { return signal_name_; }
+
+ GVariant* RemoveParam() {
+ GVariant *param = param_;
+ param_ = nullptr;
+ return param;
+ }
+
+ bool IsDone() const { return done_; }
+
+ const std::string& GetLogMessage() const { return log_message_; }
+
+ private:
+ bool done_ = false;
+ std::string path_;
+ std::string interface_;
+ std::string signal_name_;
+ GVariant *param_ = nullptr;
+ std::string log_message_;
+};
+
+class DBusManager {
+ public:
+ DBusManager(const DBusManager&) = delete;
+ DBusManager& operator = (const DBusManager&) = delete;
+ DBusManager(DBusManager&&) = delete;
+ DBusManager& operator = (DBusManager&&) = delete;
+
+ static DBusManager& GetInst() {
+ static DBusManager inst;
+ inst.Init();
+ return inst;
+ }
+
+ void Dispose() {
+ if (disposed_)
+ return;
+
+ if (getpid() == pid_) {
+ queue_.Push(std::make_shared<DBusMessage>(true));
+ thread_.join();
+
+ if (conn_ != nullptr) {
+ g_object_unref(conn_);
+ conn_ = nullptr;
+ }
+ }
+
+ disposed_ = true;
+ }
+
+ void Send(std::shared_ptr<DBusMessage> message) {
+ queue_.Push(std::move(message));
+ }
+
+ private:
+ DBusManager() = default;
+ ~DBusManager() { Dispose(); }
+
+ void Init() {
+ if (!disposed_)
+ return;
+
+ thread_ = std::thread([&]() -> void { WorkerThread(); });
+ disposed_ = false;
+ }
+
+ GDBusConnection* GetConnection() {
+ if (conn_)
+ return conn_;
+
+ GError* error = nullptr;
+ conn_ = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
+ if (conn_ == nullptr) {
+ error_count_++;
+ if (error_count_ < ERROR_THRESHOLD || error_count_ % ERROR_MODULO == 0) {
+ _E("g_bus_get_sync() is failed. error(%s)",
+ error ? error->message : "Unknown");
+ }
+
+ g_clear_error(&error);
+ return nullptr;
+ }
+
+ return conn_;
+ }
+
+ void EmitSignal(std::shared_ptr<DBusMessage> args) {
+ GError* error = nullptr;
+ if (!g_dbus_connection_emit_signal(conn_, nullptr, args->GetPath().c_str(),
+ args->GetInterface().c_str(), args->GetSignalName().c_str(),
+ args->RemoveParam(), &error)) {
+ _E("g_dbus_connection_emit_signal() is failed. error(%s)",
+ error ? error->message : "Unknown");
+ g_clear_error(&error);
+ return;
+ }
+
+ if (!g_dbus_connection_flush_sync(conn_, nullptr, &error)) {
+ _E("g_dbus_connection_flush_sync() is failed. error(%s)",
+ error ? error->message : "Unknown");
+ g_clear_error(&error);
+ return;
+ }
+
+ _W("[DBUS] %s", args->GetLogMessage().c_str());
+ }
+
+ void WorkerThread() {
+ _W("BEGIN");
+ while (true) {
+ auto conn = GetConnection();
+ if (conn == nullptr) {
+ _W("Wait for dbus ready");
+ std::this_thread::sleep_for(
+ std::chrono::milliseconds(PENDING_ITEM_INTERVAL));
+ continue;
+ }
+
+ auto message = queue_.WaitAndPop();
+ if (message->IsDone())
+ break;
+
+ EmitSignal(message);
+ }
+ _W("END");
+ }
+
+ private:
+ bool disposed_ = true;
+ pid_t pid_ = getpid();
+ GDBusConnection* conn_ = nullptr;
+ uint32_t error_count_ = 0;
+ std::thread thread_;
+ tizen_base::SharedQueue<std::shared_ptr<DBusMessage>> queue_;
+};
+
+} // namespace
+
+void DBus::SendAppLaunchSignal(pid_t pid, const std::string_view appid) {
+ DBusManager::GetInst().Send(
+ std::make_shared<DBusMessage>(
+ AUL_DBUS_PATH, AUL_DBUS_SIGNAL_INTERFACE, AUL_DBUS_APPLAUNCH_SIGNAL,
+ g_variant_new("(us)", pid, appid.data()),
+ "App Launch. " + std::to_string(pid) + ":" + std::string(appid)));
+}
+
+void DBus::SendAppDeadSignal(pid_t pid) {
+ DBusManager::GetInst().Send(
+ std::make_shared<DBusMessage>(
+ AUL_DBUS_PATH, AUL_DBUS_SIGNAL_INTERFACE, AUL_DBUS_APPDEAD_SIGNAL,
+ g_variant_new("(u)", pid), "App Dead. " + std::to_string(pid)));
+}
+
+} // namespace launchpad
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2023 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.
* limitations under the License.
*/
-#ifndef __LAUNCHPAD_DBUS_H__
-#define __LAUNCHPAD_DBUS_H__
+#ifndef LAUNCHPAD_PROCESS_POOL_DBUS_HH_
+#define LAUNCHPAD_PROCESS_POOL_DBUS_HH_
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <sys/types.h>
+#include <unistd.h>
-int _dbus_send_app_launch_signal(int pid, const char *app_id);
+#include <string>
-int _dbus_send_app_dead_signal(int pid);
+namespace launchpad {
-int _dbus_init(void);
+class DBus {
+ public:
+ static void SendAppLaunchSignal(pid_t pid, const std::string_view appid);
+ static void SendAppDeadSignal(pid_t pid);
+};
-void _dbus_fini(void);
+} // namespace launchpad
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __LAUNCHPAD_DBUS_H__ */
+#endif // LAUNCHPAD_PROCESS_POOL_DBUS_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_dbus.h"
#include "launchpad-process-pool/launchpad_debug.h"
#include "launchpad-process-pool/launchpad_inotify.h"
#include "launchpad-process-pool/launchpad_io_channel.h"
#include "lib/common/inc/launchpad_types.h"
#include "lib/common/inc/perf.h"
+#include "launchpad-process-pool/dbus.hh"
#include "launchpad-process-pool/log.hh"
#define AUL_PR_NAME 16
__request_send_result(request, request->pid);
if (request->pid > 0) {
- _dbus_send_app_launch_signal(request->pid, request->menu_info->appid);
+ launchpad::DBus::SendAppLaunchSignal(request->pid,
+ request->menu_info->appid);
g_hash_table_insert(__pid_table, GINT_TO_POINTER(request->pid),
strdup(request->menu_info->appid));
launchpad::Log::Print("[LAUNCH]", "pid(%7d) | appid(%s)",
if (ret != 0)
_W("Failed to initialize config");
- ret = _dbus_init();
- if (ret != 0)
- _W("Failed to initialize dbus");
-
_inotify_init();
_memory_monitor_init();
_memory_monitor_set_event_cb(__memory_monitor_cb, nullptr);
_debug_fini();
launcher_info_list.clear();
- _dbus_fini();
_config_fini();
_inotify_fini();
app_defined_loader_info_manager->Dispose();
+++ /dev/null
-/*
- * Copyright (c) 2020 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_dbus.h"
-
-#include <gio/gio.h>
-#include <glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "lib/common/inc/log_private.h"
-
-#define AUL_DBUS_PATH "/aul/dbus_handler"
-#define AUL_DBUS_SIGNAL_INTERFACE "org.tizen.aul.signal"
-#define AUL_DBUS_APPDEAD_SIGNAL "app_dead"
-#define AUL_DBUS_APPLAUNCH_SIGNAL "app_launch"
-
-#define PENDING_ITEM_INTERVAL 1000
-
-#define GET_CONNECTION_ERROR_THRESHOLD 10
-#define GET_CONNECTION_ERROR_MODULO 1000
-typedef enum {
- APP_SIGNAL_DEAD,
- APP_SIGNAL_LAUNCH,
-} app_signal_e;
-
-typedef struct pending_item_s {
- char* app_id;
- int pid;
- app_signal_e app_signal;
-} pending_item_t;
-
-static GList* __pending_items;
-static guint __timer;
-static GDBusConnection* __conn;
-
-static void __set_pending_item_timer(void);
-
-static void __destroy_pending_item(gpointer data) {
- auto* item = static_cast<pending_item_t*>(data);
-
- free(item->app_id);
- free(item);
-}
-
-static pending_item_t* __create_pending_item(const char* app_id,
- int pid,
- app_signal_e app_signal) {
- pending_item_t* item;
-
- item = static_cast<pending_item_t*>(calloc(1, sizeof(pending_item_t)));
- if (!item) {
- _E("Out of memory");
- return nullptr;
- }
-
- if (app_id) {
- item->app_id = strdup(app_id);
- if (!item->app_id) {
- _E("Failed to duplicate app ID(%s)", app_id);
- __destroy_pending_item(item);
- return nullptr;
- }
- }
-
- item->pid = pid;
- item->app_signal = app_signal;
-
- return item;
-}
-
-static GDBusConnection* __get_connection(void) {
- GError* error = nullptr;
- static unsigned int error_count = 0;
-
- if (__conn)
- return __conn;
-
- __conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
- if (!__conn) {
- error_count++;
- if (error_count < GET_CONNECTION_ERROR_THRESHOLD ||
- error_count % GET_CONNECTION_ERROR_MODULO == 0) {
- _E("g_bus_get_sync() is failed. error(%s)",
- error ? error->message : "Unknown");
- }
-
- g_clear_error(&error);
- return nullptr;
- }
-
- return __conn;
-}
-
-static int __emit_signal(const char* path,
- const char* interface,
- const char* signal,
- GVariant* param) {
- GDBusConnection* conn;
- GError* error = nullptr;
- gboolean ret;
-
- conn = __get_connection();
- if (!conn)
- return -1;
-
- ret = g_dbus_connection_emit_signal(conn, nullptr, path, interface, signal,
- param, &error);
- if (ret != TRUE) {
- _E("g_dbus_connection_emit_signal() is failed. error(%s)",
- error ? error->message : "Unknown");
- g_clear_error(&error);
- return -1;
- }
-
- ret = g_dbus_connection_flush_sync(conn, nullptr, &error);
- if (ret != TRUE) {
- _E("g_dbus_connection_flush_sync() is failed. error(%s)",
- error ? error->message : "Unknown");
- g_clear_error(&error);
- return -1;
- }
-
- return 0;
-}
-
-static int __emit_app_launch_signal(int pid, const char* app_id) {
- int ret;
-
- ret = __emit_signal(AUL_DBUS_PATH, AUL_DBUS_SIGNAL_INTERFACE,
- AUL_DBUS_APPLAUNCH_SIGNAL,
- g_variant_new("(us)", pid, app_id));
- if (ret < 0)
- return ret;
-
- _D("App launch. pid(%d), app_id(%s)", pid, app_id);
-
- return 0;
-}
-
-static int __emit_app_dead_signal(int pid) {
- int ret;
-
- ret = __emit_signal(AUL_DBUS_PATH, AUL_DBUS_SIGNAL_INTERFACE,
- AUL_DBUS_APPDEAD_SIGNAL, g_variant_new("(u)", pid));
- if (ret < 0)
- return ret;
-
- _D("App dead. pid(%d)", pid);
-
- return 0;
-}
-
-static gboolean __flush_pending_item(gpointer data) {
- pending_item_t* item;
- GList* iter;
- int ret;
-
- if (!__pending_items) {
- __timer = 0;
- return G_SOURCE_REMOVE;
- }
-
- iter = __pending_items;
- while (iter) {
- item = (pending_item_t*)iter->data;
- if (item->app_signal == APP_SIGNAL_DEAD)
- ret = __emit_app_dead_signal(item->pid);
- else
- ret = __emit_app_launch_signal(item->pid, item->app_id);
-
- if (ret < 0)
- return G_SOURCE_CONTINUE;
-
- iter = g_list_next(iter);
- __pending_items = g_list_remove(__pending_items, item);
- __destroy_pending_item(item);
- }
-
- __timer = 0;
- return G_SOURCE_REMOVE;
-}
-
-static void __set_pending_item_timer(void) {
- if (__timer)
- return;
-
- __timer = g_timeout_add(PENDING_ITEM_INTERVAL, __flush_pending_item, nullptr);
-}
-
-static void __unset_pending_item_timer(void) {
- if (!__timer)
- return;
-
- g_source_remove(__timer);
- __timer = 0;
-}
-
-int _dbus_send_app_launch_signal(int pid, const char* app_id) {
- pending_item_t* item;
- int ret;
-
- if (pid <= 1 || !app_id) {
- _E("Invalid parameter");
- return -EINVAL;
- }
-
- ret = __emit_app_launch_signal(pid, app_id);
- if (ret < 0) {
- item = __create_pending_item(app_id, pid, APP_SIGNAL_LAUNCH);
- if (!item)
- return -ENOMEM;
-
- _W("Pend app launch signal. pid(%d), app_id(%s)", pid, app_id);
- __pending_items = g_list_append(__pending_items, item);
- __set_pending_item_timer();
- }
-
- return 0;
-}
-
-int _dbus_send_app_dead_signal(int pid) {
- pending_item_t* item;
- int ret;
-
- if (pid <= 1) {
- _E("Invalid parameter");
- return -EINVAL;
- }
-
- ret = __emit_app_dead_signal(pid);
- if (ret < 0) {
- item = __create_pending_item(nullptr, pid, APP_SIGNAL_DEAD);
- if (!item)
- return -ENOMEM;
-
- _W("Pend app dead signal. pid(%d)", pid);
- __pending_items = g_list_append(__pending_items, item);
- __set_pending_item_timer();
- }
-
- return 0;
-}
-
-int _dbus_init(void) {
- GDBusConnection* conn;
-
- _D("DBUS_INIT");
- conn = __get_connection();
- if (!conn)
- return -1;
-
- return 0;
-}
-
-void _dbus_fini(void) {
- _D("DBUS_FINI");
- if (__pending_items)
- g_list_free_full(__pending_items, __destroy_pending_item);
-
- __unset_pending_item_timer();
-
- if (__conn)
- g_object_unref(__conn);
-}
#include <sys/types.h>
#include <algorithm>
-#include <fstream>
-#include <utility>
#include "launchpad-process-pool/debugger_info.hh"
#include "lib/common/inc/key.h"
#include <string>
#include <vector>
-#include "launchpad-process-pool/launchpad_dbus.h"
#include "launchpad-process-pool/launchpad_io_channel.h"
#include "launchpad-process-pool/launchpad_worker.h"
#include "lib/common/inc/launchpad_common.h"
#include "lib/common/inc/launchpad_socket.h"
#include "lib/common/inc/log_private.h"
+#include "launchpad-process-pool/dbus.hh"
+
namespace {
constexpr const char HYDRA_SIGCHLD_SOCK[] = ".hydra-sigchld-sock";
}
static void __sigchld_action(int pid) {
- _dbus_send_app_dead_signal(pid);
+ launchpad::DBus::SendAppDeadSignal(pid);
_worker_add_job(recycle_bin, __garbage_collector, GINT_TO_POINTER(pid));
}
LIBTZPLATFORM_CONFIG_DEPS
SECURITY_MANAGER_DEPS
TANCHOR_DEPS
+ TIZEN_SHARED_QUEUE_DEPS
TTRACE_DEPS
VCONF_DEPS
GMOCK_DEPS