From: Changgyu Choi Date: Wed, 9 Apr 2025 01:41:20 +0000 (+0900) Subject: Implement FdMonitor X-Git-Tag: accepted/tizen/unified/20250516.055915~7^2~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=182d77a387d0a7cd2b0b12c7cbd75d5a923f2f61;p=platform%2Fcore%2Fappfw%2Funited-service.git Implement FdMonitor Signed-off-by: Changgyu Choi --- diff --git a/src/activation_method/fd_monitor.cc b/src/activation_method/fd_monitor.cc index e93b192..8439869 100644 --- a/src/activation_method/fd_monitor.cc +++ b/src/activation_method/fd_monitor.cc @@ -1,16 +1,67 @@ #include "fd_monitor.hh" -tizen_base::FdMonitor::FdMonitor(std::string, - int fd, - IEventListener* listener) {} - -tizen_base::FdMonitor::FdMonitor(std::string name, - std::string path, - IEventListener* listener) {} - -gboolean tizen_base::FdMonitor::UnixFdSourceFunc(gint fd, - GIOCondition cond, - gpointer data) { - // TODO - return FALSE; +#include + +#include +#include +#include + +#include +#include + +#include "../event_listener.hh" +#include "../log_private.hh" +namespace tizen_base { + +FdMonitor::FdMonitor(std::string name, int fd, IEventListener* listener) + : name_(std::move(name)), listener_(listener) {} + +FdMonitor::FdMonitor(std::string name, + std::string path, + IEventListener* listener) + : name_(std::move(name)), listener_(listener) { + int n = sd_listen_fds(0); + if (n < 0) { + throw std::runtime_error("std_listen_fds failed."); + } + + int fd = -1; + for (int i = SD_LISTEN_FDS_START; i < SD_LISTEN_FDS_START + n; i++) { + int r = sd_is_socket_unix(i, SOCK_STREAM, -1, path.c_str(), 0); + if (r > 0) { + fd = i; + break; + } + } + + if (fd == -1) + throw std::runtime_error("Can not find socket file descriptor(" + path + + ")"); + + unix_fd_source_id_ = g_unix_fd_add(fd, G_IO_IN, UnixFdSourceFunc, this); + if (unix_fd_source_id_ == 0) + throw std::runtime_error("g_unix_fd_add failed."); +} + +FdMonitor::~FdMonitor() { + if (unix_fd_source_id_) + g_source_remove(unix_fd_source_id_); } + +gboolean FdMonitor::UnixFdSourceFunc(gint fd, + GIOCondition cond, + gpointer data) { + FdMonitor* self = static_cast(data); + if (!(cond & G_IO_IN)) { + _E("G_IO_IN condition is not set. cond: %d", static_cast(cond)); + self->unix_fd_source_id_ = 0; + return G_SOURCE_REMOVE; + } + + _I("Receive event from fd(%d) name(%s)", fd, self->name_.c_str()); + self->listener_->OnEvent(self->name_); + self->unix_fd_source_id_ = 0; + return G_SOURCE_REMOVE; +} + +} // namespace tizen_base diff --git a/src/activation_method/fd_monitor.hh b/src/activation_method/fd_monitor.hh index 78da363..59c6e1c 100644 --- a/src/activation_method/fd_monitor.hh +++ b/src/activation_method/fd_monitor.hh @@ -30,8 +30,13 @@ class FdMonitor { public: FdMonitor(std::string, int fd, IEventListener* listener); FdMonitor(std::string name, std::string path, IEventListener* listener); - + ~FdMonitor(); static gboolean UnixFdSourceFunc(gint fd, GIOCondition cond, gpointer data); + + private: + guint unix_fd_source_id_ = 0; + std::string name_; + IEventListener* listener_ = nullptr; }; }; diff --git a/src/service.cc b/src/service.cc index a7e346f..6eea04e 100644 --- a/src/service.cc +++ b/src/service.cc @@ -233,7 +233,16 @@ void Service::SetStateChangedCb(StateChangedCb cb) { state_changed_cb_ = std::move(cb); } -void Service::Listen(IEventListener* listener) { +bool Service::IsMonitoring() const { + return monitoring_; +} + +void Service::StartMonitoring(IEventListener* listener) { + if (monitoring_) { + _W("Already monitoring"); + return; + } + auto type = info_->GetType(); if (type == "socket") { const auto& socket_info = info_->GetSocketInfo(); @@ -245,6 +254,15 @@ void Service::Listen(IEventListener* listener) { const auto& dbus_info = info_->GetDbusInfo(); dbus_monitor_.reset(new DBusMonitor(info_->GetName(), dbus_info->GetBusName(), listener)); } + + monitoring_ = true; +} + +void Service::StopMonitoring() { + fd_monitor_.reset(); + file_monitor_.reset(); + dbus_monitor_.reset(); + monitoring_ = false; } void Service::NotifyStateChanged() { diff --git a/src/service.hh b/src/service.hh index 0370215..5620613 100644 --- a/src/service.hh +++ b/src/service.hh @@ -71,7 +71,10 @@ class Service : public std::enable_shared_from_this { tizen_core_channel_sender_h GetChannelSender() const; void SendMessage(const tizen_base::Bundle& envelope); void SetStateChangedCb(StateChangedCb cb); - void Listen(IEventListener* listener); + + bool IsMonitoring() const; + void StartMonitoring(IEventListener* listener); + void StopMonitoring(); private: void OnBaseCreate(); @@ -96,6 +99,7 @@ class Service : public std::enable_shared_from_this { tizen_core_channel_receiver_h receiver_ = nullptr; tizen_core_source_h source_ = nullptr; std::atomic running_{false}; + std::atomic monitoring_{false}; pid_t tid_ = -1; StateChangedCb state_changed_cb_ = nullptr; diff --git a/src/service_context.cc b/src/service_context.cc deleted file mode 100644 index b8dba0e..0000000 --- a/src/service_context.cc +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2025 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 "service_context.hh" - -#include - -#include -#include - -#include "log_private.hh" - -namespace { - -constexpr const char kUnitedServiceInit[] = "UNITED_SERVICE_INIT"; -constexpr const char kUnitedServiceShutdown[] = "UNITED_SERVICE_SHUTDOWN"; - -} // namespace - -namespace tizen_base { - -ServiceContext::ServiceContext(std::shared_ptr info) - : info_(std::move(info)) {} - -ServiceContext::~ServiceContext() { Shutdown(); } - -bool ServiceContext::Init() { - if (!Load()) return false; - - auto* init_func = reinterpret_cast( - dlsym(handle_, kUnitedServiceInit)); - if (init_func == nullptr) { - _E("dlsym() is failed. error=%s", dlerror()); - Unload(); - return false; - } - - auto* handle = init_func(info_->GetName().c_str()); - if (handle == nullptr) { - _E("Failed to initialize united service"); - Unload(); - return false; - } - - auto* service = static_cast(handle); - service_ = service->shared_from_this(); - return true; -} - -void ServiceContext::Shutdown() { - if (!handle_) return; - - if (service_) service_->Quit(); - - auto* shutdown_func = - reinterpret_cast(dlsym(handle_, kUnitedServiceShutdown)); - if (shutdown_func == nullptr) { - _E("dlsym() is failed. error=%s", dlerror()); - } else { - shutdown_func(); - } - - Unload(); -} - -void ServiceContext::Listen(IEventListener* listener) { - auto type = info_->GetType(); - if (type == "socket") { - const auto& socket_info = info_->GetSocketInfo(); - fd_monitor_.reset(new FdMonitor(info_->GetName(), socket_info->GetPath(), listener)); - } else if (type == "file") { - const auto& file_info = info_->GetFileInfo(); - file_monitor_.reset(new FileMonitor(info_->GetName(), file_info->GetPath(), listener)); - } else if (type == "dbus") { - const auto& dbus_info = info_->GetDbusInfo(); - dbus_monitor_.reset(new DBusMonitor(info_->GetName(), dbus_info->GetBusName(), listener)); - } -} - -std::shared_ptr ServiceContext::GetService() const { return service_; } - -std::shared_ptr ServiceContext::GetServiceInfo() const { - return info_; -} - -const std::string& ServiceContext::GetName() const { return info_->GetName(); } - -bool ServiceContext::Load() { - if (handle_) return true; - - _D("Load(): %s", info_->GetPath().c_str()); - handle_ = dlopen(info_->GetPath().c_str(), RTLD_LAZY | RTLD_GLOBAL); - if (handle_ == nullptr) { - _E("dlopen() is failed. path=%s, error=%s", info_->GetPath().c_str(), - dlerror()); - return false; - } - - return true; -} - -void ServiceContext::Unload() { - if (!handle_) return; - - _D("Unload(): %s", info_->GetPath().c_str()); - dlclose(handle_); - handle_ = nullptr; -} - -} // namespace tizen_base - diff --git a/src/service_loader.cc b/src/service_loader.cc index 2b56b71..7814c44 100755 --- a/src/service_loader.cc +++ b/src/service_loader.cc @@ -179,9 +179,8 @@ void ServiceLoader::LoadServices() { assembly->ModuleInit(info->GetName()); } - if (info->GetMode() == "on-demand") { - - } + if (info->GetMode() == "on-demand") + ListenService(name); } catch (const Exception& e) { _E("Error=%s", e.what()); THROW(e.GetErrorCode()); @@ -243,7 +242,12 @@ void ServiceLoader::RunService(const std::string& name) { THROW(SERVICE_ERROR_INVALID_CONTEXT); } - service = std::make_shared(std::move(info), std::move(listener)); + if (service == nullptr) + service = std::make_shared(std::move(info), std::move(listener)); + + if (service->IsMonitoring()) + service->StopMonitoring(); + if (service == nullptr) { _E("Out of memory. name=%s", name.c_str()); THROW(SERVICE_ERROR_OUT_OF_MEMORY); @@ -297,7 +301,7 @@ void ServiceLoader::QuitAllServices() { } } -void ServiceLoader::ListenService(const std::string & name) { +void ServiceLoader::ListenService(const std::string& name) { auto service = GetService(name); if (service != nullptr && service->IsRunning()) { _E("Already running. name=%s", name.c_str()); @@ -326,7 +330,7 @@ void ServiceLoader::ListenService(const std::string & name) { this, std::placeholders::_1, std::placeholders::_2)); services_[name] = service; - service->Listen(); + service->StartMonitoring(this); } void ServiceLoader::LoadService(const std::string& name) { @@ -359,7 +363,7 @@ void ServiceLoader::UnloadService(const std::string& name) { THROW(SERVICE_ERROR_INVALID_CONTEXT); try { - assembly->ModuleShutdown(name.c_str()); + assembly->ModuleShutdown(name); assembly->Unload(); } catch (const Exception& e) { _E("Error=%s", e.what()); @@ -390,14 +394,12 @@ void ServiceLoader::OnServiceStateChanged(const Service* service, Service::State state) {} void ServiceLoader::OnEvent(const std::string& name) { - auto it = std::find_if(services_.begin(), services_.end(), - [&](const std::shared_ptr& service) { - return service->GetName() == name; - }); + auto it = services_.find(name); if (it != services_.end()) { _I("%s on-demand launch", name.c_str()); - auto& service = *it; + auto& service = it->second; + service->StopMonitoring(); service->Run(); } }