#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 <systemd/sd-daemon.h>
+
+#include <gio/gio.h>
+#include <glib-unix.h>
+#include <glib.h>
+
+#include <stdexcept>
+#include <utility>
+
+#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<FdMonitor*>(data);
+ if (!(cond & G_IO_IN)) {
+ _E("G_IO_IN condition is not set. cond: %d", static_cast<int>(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
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;
};
};
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();
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() {
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();
tizen_core_channel_receiver_h receiver_ = nullptr;
tizen_core_source_h source_ = nullptr;
std::atomic<bool> running_{false};
+ std::atomic<bool> monitoring_{false};
pid_t tid_ = -1;
StateChangedCb state_changed_cb_ = nullptr;
+++ /dev/null
-/*
- * 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 <dlfcn.h>
-
-#include <string>
-#include <utility>
-
-#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<ServiceInfo> info)
- : info_(std::move(info)) {}
-
-ServiceContext::~ServiceContext() { Shutdown(); }
-
-bool ServiceContext::Init() {
- if (!Load()) return false;
-
- auto* init_func = reinterpret_cast<void* (*)(const char*)>(
- 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<Service*>(handle);
- service_ = service->shared_from_this();
- return true;
-}
-
-void ServiceContext::Shutdown() {
- if (!handle_) return;
-
- if (service_) service_->Quit();
-
- auto* shutdown_func =
- reinterpret_cast<void (*)(void)>(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<Service> ServiceContext::GetService() const { return service_; }
-
-std::shared_ptr<ServiceInfo> 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
-
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());
THROW(SERVICE_ERROR_INVALID_CONTEXT);
}
- service = std::make_shared<Service>(std::move(info), std::move(listener));
+ if (service == nullptr)
+ service = std::make_shared<Service>(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);
}
}
-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());
this, std::placeholders::_1,
std::placeholders::_2));
services_[name] = service;
- service->Listen();
+ service->StartMonitoring(this);
}
void ServiceLoader::LoadService(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());
Service::State state) {}
void ServiceLoader::OnEvent(const std::string& name) {
- auto it = std::find_if(services_.begin(), services_.end(),
- [&](const std::shared_ptr<Service>& 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();
}
}