Change to delete some resource in sensor_reader thread 41/275041/1 accepted/tizen/6.5/unified/20220518.034343 submit/tizen_6.5/20220516.074100
authorTaeminYeom <taemin.yeom@samsung.com>
Tue, 10 May 2022 08:51:44 +0000 (17:51 +0900)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Sat, 14 May 2022 04:42:26 +0000 (04:42 +0000)
It fixes segmentation fault in client.

Change-Id: I15977d8189b68b5ff7e319eb344ad9ebd5e9ad80
Signed-off-by: TaeminYeom <taemin.yeom@samsung.com>
(cherry picked from commit 58a309c994c24c8cb61605cf565274d9e0f6d1c9)

20 files changed:
src/client/sensor_internal.cpp
src/client/sensor_listener.cpp
src/client/sensor_listener.h
src/client/sensor_manager_channel_handler.h
src/client/sensor_provider_channel_handler.h
src/sensorctl/testcase/unit_ipc.cpp
src/server/sensor_event_handler.cpp
src/server/sensor_event_handler.h
src/server/server_channel_handler.h
src/shared/accept_event_handler.cpp
src/shared/accept_event_handler.h
src/shared/channel.cpp
src/shared/channel_event_handler.cpp
src/shared/channel_event_handler.h
src/shared/channel_handler.h
src/shared/cmutex.cpp
src/shared/cmutex.h
src/shared/event_handler.h
src/shared/event_loop.cpp
src/shared/event_loop.h

index 312b3034881c3b39ccc7f1edf1c3d088145aacee..1930b29330bdb25cf46989283eafbc60b986827e 100644 (file)
@@ -164,7 +164,8 @@ public:
                callback_info_s *info;
                auto size = msg.size();
                char *data = new(std::nothrow) char[size];
-
+               if (data == NULL)
+                       return;
                memcpy(data, msg.body(), size);
 
                info = new(std::nothrow) callback_info_s();
@@ -180,6 +181,8 @@ public:
 
        void read_complete(ipc::channel *ch) {}
        void error_caught(ipc::channel *ch, int error) {}
+       void set_handler(int num, ipc::channel_handler* handler) {}
+       void disconnect(void) {}
 
 private:
        int m_listener_id;
index ad5be4826024cfc83bc7ba160d8fc4842284a434..44b72d92783038115f1ff9df702f1201ef024206 100644 (file)
 #include <sensor_types.h>
 #include <command_types.h>
 #include <ipc_client.h>
-#include <cmutex.h>
 
 using namespace sensor;
 
-static cmutex lock;
-
 class listener_handler : public ipc::channel_handler
 {
 public:
        listener_handler(sensor_listener *listener)
        : m_listener(listener)
-       {}
+       {
+               evt_handler[0] = evt_handler[1] = evt_handler[2] = evt_handler[3] = NULL;
+       }
 
        void connected(ipc::channel *ch) {}
        void disconnected(ipc::channel *ch)
        {
                /* If channel->disconnect() is not explicitly called,
                 * listener will be restored */
-               m_listener->restore();
+               if (m_listener)
+                       m_listener->restore();
+       }
+
+       void disconnect(void)
+       {
+               m_listener = NULL;
        }
 
        void read(ipc::channel *ch, ipc::message &msg)
        {
+               ipc::channel_handler *handler = NULL;
                switch (msg.header()->type) {
                case CMD_LISTENER_EVENT:
-                       if (m_listener->get_event_handler()) {
-                               m_listener->get_event_handler()->read(ch, msg);
-                       }
+                       handler = evt_handler[0];
+                       if (handler)
+                               handler->read(ch, msg);
                        break;
                case CMD_LISTENER_ACC_EVENT:
-                       if (m_listener->get_accuracy_handler()) {
-                               m_listener->get_accuracy_handler()->read(ch, msg);
-                       }
+                       handler = evt_handler[1];
+                       if (handler)
+                               handler->read(ch, msg);
                        break;
-               case CMD_LISTENER_SET_ATTR_INT: {
-                       if (m_listener->get_attribute_int_changed_handler()) {
-                               m_listener->get_attribute_int_changed_handler()->read(ch, msg);
-                       }
-               } break;
-               case CMD_LISTENER_SET_ATTR_STR: {
-                       if (m_listener->get_attribute_str_changed_handler()) {
-                               m_listener->get_attribute_str_changed_handler()->read(ch, msg);
-                       }
-               } break;
-               case CMD_LISTENER_CONNECTED: {
+               case CMD_LISTENER_SET_ATTR_INT:
+                       handler = evt_handler[2];
+                       if (handler)
+                               handler->read(ch, msg);
+                       break;
+               case CMD_LISTENER_SET_ATTR_STR:
+                       handler = evt_handler[3];
+                       if (handler)
+                               handler->read(ch, msg);
+                       break;
+               case CMD_LISTENER_CONNECTED:
                        // Do nothing
-               } break;
+                       break;
                default:
                        _W("Invalid command message");
                }
        }
 
+       void set_handler(int num, ipc::channel_handler* handler) {
+               evt_handler[num] = handler;
+       }
+
        void read_complete(ipc::channel *ch) {}
        void error_caught(ipc::channel *ch, int error) {}
 
 private:
+       ipc::channel_handler *evt_handler[4];
        sensor_listener *m_listener;
 };
 
@@ -147,27 +158,22 @@ bool sensor_listener::init(void)
 
 void sensor_listener::deinit(void)
 {
+       AUTOLOCK(lock);
        _D("Deinitializing..");
        stop();
        disconnect();
 
-       delete m_handler;
+       m_handler->disconnect();
+       m_loop->add_channel_handler_release_list(m_handler);
        m_handler = NULL;
 
        delete m_client;
        m_client = NULL;
 
-       delete m_evt_handler;
-       m_evt_handler = NULL;
-
-       delete m_acc_handler;
-       m_acc_handler = NULL;
-
-       delete m_attr_int_changed_handler;
-       m_attr_int_changed_handler = NULL;
-
-       delete m_attr_str_changed_handler;
-       m_attr_str_changed_handler = NULL;
+       unset_event_handler();
+       unset_accuracy_handler();
+       unset_attribute_int_changed_handler();
+       unset_attribute_str_changed_handler();
 
        m_attributes_int.clear();
        m_attributes_str.clear();
@@ -186,7 +192,8 @@ sensor_t sensor_listener::get_sensor(void)
 
 void sensor_listener::restore(void)
 {
-       ret_if(!is_connected());
+       if (lock.try_lock())
+               return;
 
        m_cmd_channel->disconnect();
        delete m_cmd_channel;
@@ -213,6 +220,7 @@ void sensor_listener::restore(void)
                set_attribute(SENSORD_ATTRIBUTE_PAUSE_POLICY, m_attributes_int[SENSORD_ATTRIBUTE_PAUSE_POLICY]);
 
        _D("Restored listener[%d]", get_id());
+       lock.unlock();
 }
 
 bool sensor_listener::connect(void)
@@ -252,8 +260,7 @@ void sensor_listener::disconnect(void)
 
        _D("Disconnecting..");
 
-       m_evt_channel->disconnect();
-       delete m_evt_channel;
+       m_loop->add_channel_release_queue(m_evt_channel);
        m_evt_channel = NULL;
 
        m_cmd_channel->disconnect();
@@ -270,92 +277,90 @@ bool sensor_listener::is_connected(void)
 
 ipc::channel_handler *sensor_listener::get_event_handler(void)
 {
-       AUTOLOCK(lock);
-
        return m_evt_handler;
 }
 
 void sensor_listener::set_event_handler(ipc::channel_handler *handler)
 {
-       AUTOLOCK(lock);
-       if (m_evt_handler) {
-               delete m_evt_handler;
-       }
+       m_handler->set_handler(0, handler);
+       if (m_evt_handler)
+               m_loop->add_channel_handler_release_list(m_evt_handler);
        m_evt_handler = handler;
 }
 
 void sensor_listener::unset_event_handler(void)
 {
-       AUTOLOCK(lock);
-
-       delete m_evt_handler;
-       m_evt_handler = NULL;
+       if (m_evt_handler) {
+               m_handler->set_handler(0, NULL);
+               m_loop->add_channel_handler_release_list(m_evt_handler);
+               m_evt_handler = NULL;
+       }
 }
 
 ipc::channel_handler *sensor_listener::get_accuracy_handler(void)
 {
-       AUTOLOCK(lock);
        return m_acc_handler;
 }
 
 void sensor_listener::set_accuracy_handler(ipc::channel_handler *handler)
 {
-       AUTOLOCK(lock);
-       if (m_acc_handler) {
-               delete m_acc_handler;
-       }
+       m_handler->set_handler(1, handler);
+       if (m_acc_handler)
+               m_loop->add_channel_handler_release_list(m_acc_handler);
        m_acc_handler = handler;
 }
 
 void sensor_listener::unset_accuracy_handler(void)
 {
-       AUTOLOCK(lock);
-       delete m_acc_handler;
-       m_acc_handler = NULL;
+       if (m_acc_handler) {
+               m_handler->set_handler(1, NULL);
+               m_loop->add_channel_handler_release_list(m_acc_handler);
+               m_acc_handler = NULL;
+       }
 }
 
 ipc::channel_handler *sensor_listener::get_attribute_int_changed_handler(void)
 {
-       AUTOLOCK(lock);
        return m_attr_int_changed_handler;
 }
 
 void sensor_listener::set_attribute_int_changed_handler(ipc::channel_handler *handler)
 {
-       AUTOLOCK(lock);
-       if (m_attr_int_changed_handler) {
-               delete m_attr_int_changed_handler;
-       }
+       m_handler->set_handler(2, handler);
+       if (m_attr_int_changed_handler)
+               m_loop->add_channel_handler_release_list(m_attr_int_changed_handler);
        m_attr_int_changed_handler = handler;
 }
 
 void sensor_listener::unset_attribute_int_changed_handler(void)
 {
-       AUTOLOCK(lock);
-       delete m_attr_int_changed_handler;
-       m_attr_int_changed_handler = NULL;
+       if (m_attr_int_changed_handler) {
+               m_handler->set_handler(2, NULL);
+               m_loop->add_channel_handler_release_list(m_attr_int_changed_handler);
+               m_attr_int_changed_handler = NULL;
+       }
 }
 
 ipc::channel_handler *sensor_listener::get_attribute_str_changed_handler(void)
 {
-       AUTOLOCK(lock);
        return m_attr_str_changed_handler;
 }
 
 void sensor_listener::set_attribute_str_changed_handler(ipc::channel_handler *handler)
 {
-       AUTOLOCK(lock);
-       if (m_attr_str_changed_handler) {
-               delete m_attr_str_changed_handler;
-       }
+       m_handler->set_handler(3, handler);
+       if (m_attr_str_changed_handler)
+               m_loop->add_channel_handler_release_list(m_attr_str_changed_handler);
        m_attr_str_changed_handler = handler;
 }
 
 void sensor_listener::unset_attribute_str_changed_handler(void)
 {
-       AUTOLOCK(lock);
-       delete m_attr_str_changed_handler;
-       m_attr_str_changed_handler = NULL;
+       if (m_attr_str_changed_handler) {
+               m_handler->set_handler(3, NULL);
+               m_loop->add_channel_handler_release_list(m_attr_str_changed_handler);
+               m_attr_str_changed_handler = NULL;
+       }
 }
 
 int sensor_listener::start(void)
index c83133cae4eb282d0804c3dd4f350cb7f8b7943a..aed8b116204c5aa1af2a990e6578c383c8039ef9 100644 (file)
@@ -26,6 +26,7 @@
 #include <event_loop.h>
 #include <sensor_info.h>
 #include <sensor_types.h>
+#include <cmutex.h>
 #include <map>
 #include <atomic>
 #include <vector>
@@ -105,6 +106,8 @@ private:
        std::atomic<bool> m_started;
        std::map<int, int> m_attributes_int;
        std::map<int, std::vector<char>> m_attributes_str;
+
+       cmutex lock;
 };
 
 }
index 2bbc4c2fbf53e6ccb91a721c992b1879f2cd874e..99f76ed17b67b8069e7fdbe0d7d9e12e73dda28c 100644 (file)
@@ -47,6 +47,9 @@ public:
        void add_sensor_removed_cb(sensord_removed_cb cb, void *user_data);
        void remove_sensor_removed_cb(sensord_removed_cb cb);
 
+       void set_handler(int num, ipc::channel_handler* handler) {}
+       void disconnect(void) {}
+
 private:
        typedef std::map<sensord_added_cb, void *> sensor_added_cb_list_t;
        typedef std::map<sensord_removed_cb, void *> sensor_removed_cb_list_t;
index 89a0e36dc90b08212c7c1032ce9963add9a1cd5f..d53867cf276811fabfe7a610210f45c75eb256d2 100644 (file)
@@ -42,7 +42,8 @@ public:
        void set_stop_cb(sensord_provider_stop_cb cb, void *user_data);
        void set_interval_cb(sensord_provider_interval_changed_cb cb, void *user_data);
        void set_attribute_str_cb(sensord_provider_attribute_str_cb cb, void *user_data);
-
+       void set_handler(int num, ipc::channel_handler* handler) {}
+       void disconnect(void) {}
 private:
        sensor_provider *m_provider;
 
index ab51d65f9b0b78a35726f81d78c636fe320f0692..50b9df250f1e8221a889796d2420c5299c86cff1 100644 (file)
@@ -71,6 +71,8 @@ public:
        }
        void read_complete(channel *ch) {}
        void error_caught(channel *ch, int error) {}
+       void set_handler(int num, channel_handler *handler) {}
+       void disconnect(void) {}
 };
 
 /* IPC Echo Server */
@@ -99,6 +101,8 @@ public:
        void read(channel *ch, message &msg) {}
        void read_complete(channel *ch) {}
        void error_caught(channel *ch, int error) {}
+       void set_handler(int num, channel_handler *handler) {}
+       void disconnect(void) {}
 };
 
 /* IPC Client Sleep Test(4096Kb * 1024) */
@@ -232,6 +236,8 @@ public:
        }
        void read_complete(channel *ch) {}
        void error_caught(channel *ch, int error) {}
+       void set_handler(int num, channel_handler *handler) {}
+       void disconnect(void) {}
 };
 
 static bool run_ipc_server(const char *str, int size, int count)
@@ -262,6 +268,8 @@ public:
        void read(channel *ch, message &msg) {}
        void read_complete(channel *ch) {}
        void error_caught(channel *ch, int error) {}
+       void set_handler(int num, channel_handler *handler) {}
+       void disconnect(void) {}
 };
 
 static bool run_ipc_client_2_channel_message(const char *str, int size, int count)
index 2f7ddcffb088025fd9378c33257db38d059920ff..77da5a5fd0480e5a283b7efa669f6a31e15798b8 100644 (file)
@@ -45,10 +45,10 @@ void sensor_event_handler::remove_sensor(physical_sensor_handler *sensor)
        m_sensors.erase(sensor);
 }
 
-bool sensor_event_handler::handle(int fd, ipc::event_condition condition)
+bool sensor_event_handler::handle(int fd, ipc::event_condition condition, void **data)
 {
        sensor_info info;
-       sensor_data_t *data;
+       sensor_data_t *sensor_data;
        physical_sensor_handler *sensor;
        int length = 0;
        int remains;
@@ -74,22 +74,22 @@ bool sensor_event_handler::handle(int fd, ipc::event_condition condition)
                        continue;
 
                while (remains > 0) {
-                       remains = sensor->get_data(&data, &length);
+                       remains = sensor->get_data(&sensor_data, &length);
                        if (remains < 0) {
                                _E("Failed to get sensor data");
                                break;
                        }
 
-                       if (sensor->on_event(data, length, remains) < 0) {
-                               free(data);
+                       if (sensor->on_event(sensor_data, length, remains) < 0) {
+                               free(sensor_data);
                                continue;
                        }
 
                        info = sensor->get_sensor_info();
 
-                       //_I("[Data] allocate %p", data);
-                       if (sensor->notify(info.get_uri().c_str(), data, length) < 0) {
-                               free(data);
+                       //_I("[Data] allocate %p", sensor_data);
+                       if (sensor->notify(info.get_uri().c_str(), sensor_data, length) < 0) {
+                               free(sensor_data);
                        }
                        info.clear();
                }
index f956fddbd34564a5c275dfb1e3cffff56b72dbfa..9d37b0a9c25588592966616a9204aa792e17261a 100644 (file)
@@ -35,7 +35,7 @@ public:
        void add_sensor(physical_sensor_handler *sensor);
        void remove_sensor(physical_sensor_handler *sensor);
 
-       bool handle(int fd, ipc::event_condition condition);
+       bool handle(int fd, ipc::event_condition condition, void **data);
 
 private:
        std::set<physical_sensor_handler *> m_sensors;
index 456c4d1d8d7b15a8ab3037e3c5a75666c5631d15..fcb1735f3f7589d71a80e43735111324a1764b6c 100644 (file)
@@ -42,6 +42,8 @@ public:
        void read(ipc::channel *ch, ipc::message &msg);
        void read_complete(ipc::channel *ch) {}
        void error_caught(ipc::channel *ch, int error) {}
+       void set_handler(int num, ipc::channel_handler* handler) {}
+       void disconnect(void) {}
 
 private:
        int manager_connect(ipc::channel *ch, ipc::message &msg);
index 527d967bf0b7e5714de43afebca4efb12499ee60..b942095d2faa9b2de0cbcaf84e6f4c4993275db7 100644 (file)
@@ -29,7 +29,7 @@ accept_event_handler::accept_event_handler(ipc_server *server)
 {
 }
 
-bool accept_event_handler::handle(int fd, event_condition condition)
+bool accept_event_handler::handle(int fd, event_condition condition, void **data)
 {
        retv_if((condition & (EVENT_HUP)), false);
 
index 814f56029c8bd1ed4e4290a6593adcf942e841a0..b732238ef70a1a2a82aacc7980108c6c7ea39b5a 100644 (file)
@@ -31,7 +31,7 @@ class accept_event_handler : public event_handler
 public:
        accept_event_handler(ipc_server *server);
 
-       bool handle(int fd, event_condition condition);
+       bool handle(int fd, event_condition condition, void **data);
 
 private:
        ipc_server *m_server;
index e995057635c243c1bcae2dc4a4c4ca024c9fa601..ff4edc7128b9ee3990ba1b8043822db3944b3643 100644 (file)
@@ -47,7 +47,7 @@ public:
                }
        }
 
-       bool handle(int fd, event_condition condition)
+       bool handle(int fd, event_condition condition, void** data)
        {
                if (!m_ch) {
                        return false;
@@ -82,7 +82,7 @@ public:
        : m_ch(ch)
        { }
 
-       bool handle(int fd, event_condition condition)
+       bool handle(int fd, event_condition condition, void **data)
        {
                if (!m_ch) {
                        return false;
@@ -160,7 +160,8 @@ uint64_t channel::connect(channel_handler *handler, event_loop *loop, bool loop_
        if (!m_socket->connect())
                return false;
 
-       bind(handler, loop, loop_bind);
+       if (handler)
+               bind(handler, loop, loop_bind);
 
        _D("Connect channel[%p] : event id[%llu]", this, m_event_id);
        return m_event_id;
@@ -294,12 +295,9 @@ bool channel::read_sync(message &msg, bool select)
 
        /* header */
        size = m_socket->recv(&header, sizeof(message_header), select);
-       if (size <= 0) {
-               if (size == -1) {
-                       disconnect();
-               }
+       if (size <= 0)
                return false;
-       }
+
        /* check error from header */
        if (m_handler && header.err != 0) {
                m_handler->error_caught(this, header.err);
@@ -315,12 +313,8 @@ bool channel::read_sync(message &msg, bool select)
 
        if (header.length > 0) {
                size = m_socket->recv(&buf, header.length, select);
-               if (size <= 0) {
-                       if (size == -1) {
-                               disconnect();
-                       }
+               if (size <= 0)
                        return false;
-               }
        }
 
        buf[header.length] = '\0';
index f7f32814a627b583143269922de706eee4feb82b..7a22461ae07d203b2314beea08220188cb05ccd9 100644 (file)
@@ -39,7 +39,7 @@ channel_event_handler::~channel_event_handler()
        m_handler = NULL;
 }
 
-bool channel_event_handler::handle(int fd, event_condition condition)
+bool channel_event_handler::handle(int fd, event_condition condition, void **data)
 {
        message msg;
 
@@ -47,9 +47,8 @@ bool channel_event_handler::handle(int fd, event_condition condition)
                return false;
 
        if (condition & (EVENT_HUP)) {
-               _D("Disconnect[%p] : The other proccess is dead", this);
-               m_ch->disconnect();
-               delete m_ch;
+               //delete m_ch in g_io_handler to prevent double delete.
+               *data = m_ch;
                m_ch = NULL;
                return false;
        }
index 252c7ee0aa9d43c8a50be0a5e5ed4c7e9c076ba0..85a3efd2d0f2abb164444c063fcde671a94d11a8 100644 (file)
@@ -34,7 +34,7 @@ public:
        channel_event_handler(channel *ch, channel_handler *handler);
        virtual ~channel_event_handler();
 
-       bool handle(int fd, event_condition condition);
+       bool handle(int fd, event_condition condition, void **data);
 
        void connected(channel *ch);
        void disconnected(channel *ch);
@@ -42,6 +42,9 @@ public:
        void read_complete(channel *ch);
        void error_caught(channel *ch, int error);
 
+       void set_handler(int num, channel_handler* handler) {}
+       void disconnect(void) {}
+
 private:
        channel *m_ch;
        channel_handler *m_handler;
index b420fbde62421e704decc8f31b9f46135c5a5b10..abcab1965a43fb031d061b161d9774f2789d5b6d 100644 (file)
@@ -24,6 +24,7 @@ namespace ipc {
 
 class channel;
 class message;
+class channel_handler;
 
 class channel_handler {
 public:
@@ -31,9 +32,11 @@ public:
 
        virtual void connected(channel *ch) = 0;
        virtual void disconnected(channel *ch) = 0;
+       virtual void disconnect(void) = 0;
        virtual void read(channel *ch, message &msg) = 0;
        virtual void read_complete(channel *ch) = 0;
        virtual void error_caught(channel *ch, int error) = 0;
+       virtual void set_handler(int num, channel_handler* handler) = 0;
 };
 
 }
index 958835cb3ae2d91aac30e2d73849c69dad0591af..d3d19dd5679d1cf5bf0edadc0edb0520ed0afb4e 100644 (file)
@@ -50,6 +50,11 @@ void cmutex::lock(const char* expr, const char *module, const char *func, int li
        cbase_lock::lock(LOCK_TYPE_MUTEX, expr, module, func, line);
 }
 
+int cmutex::try_lock(void)
+{
+       return try_lock_impl();
+}
+
 int cmutex::lock_impl(void)
 {
        return pthread_mutex_lock(&m_mutex);
index 343a260e332a5ea237b70dcc267169728d7ce48d..b6c3d4d48666b83a8126b2c3e325057b4a116ad4 100644 (file)
@@ -30,6 +30,7 @@ public:
 
        void lock(void);
        void lock(const char* expr, const char *module, const char *func, int line);
+       int try_lock(void);
 
 protected:
        int lock_impl(void);
index e75b822352fbd1469b45ba9997d1d317601239db..7d1696aac9427061b283045d5058f220453a2bcc 100644 (file)
@@ -34,7 +34,7 @@ public:
 
        virtual ~event_handler() {}
 
-       virtual bool handle(int fd, event_condition condition) = 0;
+       virtual bool handle(int fd, event_condition condition, void **data) = 0;
        void set_event_id(uint64_t event_id)
        {
                m_event_id = event_id;
index f1733b2f26aa22abea4a49ec80f358a4ed29c10b..1db808c98eeb8f6ff6100dec7aeaecab3515280c 100644 (file)
 #include <time.h>
 #include <sys/eventfd.h>
 #include <glib.h>
-#include "channel_event_handler.h"
 
+#include <vector>
+#include <queue>
+
+#include "channel_event_handler.h"
 #include "sensor_log.h"
 #include "event_handler.h"
+#include "channel.h"
 
 #define BAD_HANDLE 0
 
 using namespace ipc;
 using namespace sensor;
 
+static std::vector<channel_handler*> channel_handler_release_list;
+static std::priority_queue<channel*> channel_release_queue;
+static sensor::cmutex release_lock;
+
+static void release_res()
+{
+       AUTOLOCK(release_lock);
+
+       channel *prev = NULL, *current = NULL;
+       while (!channel_release_queue.empty()) {
+               current = channel_release_queue.top();
+               if (prev != current)
+                       delete current;
+               prev = current;
+               channel_release_queue.pop();
+       }
+
+       for (auto &it : channel_handler_release_list)
+               delete it;
+       channel_handler_release_list.clear();
+}
+
 static gboolean g_io_handler(GIOChannel *ch, GIOCondition condition, gpointer data)
 {
        uint64_t id;
@@ -62,14 +88,23 @@ static gboolean g_io_handler(GIOChannel *ch, GIOCondition condition, gpointer da
        if (cond & G_IO_NVAL)
                return G_SOURCE_REMOVE;
 
-       ret = handler->handle(fd, (event_condition)cond);
+       void *addr = NULL;
+       ret = handler->handle(fd, (event_condition)cond, &addr);
 
        if (!ret && !term) {
-               loop->remove_event(id);
-               return G_SOURCE_REMOVE;
+               LOCK(release_lock);
+               channel_release_queue.push((channel*)addr);
+               UNLOCK(release_lock);
+               if (!addr)
+                       loop->remove_event(id);
+               ret = G_SOURCE_REMOVE;
+       } else {
+               ret = G_SOURCE_CONTINUE;
        }
 
-       return G_SOURCE_CONTINUE;
+       release_res();
+
+       return ret;
 }
 
 static gint on_timer(gpointer data)
@@ -227,6 +262,18 @@ void event_loop::release_info(handler_info *info)
        /* _D("Released event[%llu]", info->id); */
 }
 
+void event_loop::add_channel_release_queue(channel *ch)
+{
+       AUTOLOCK(release_lock);
+       channel_release_queue.push(ch);
+}
+
+void event_loop::add_channel_handler_release_list(channel_handler *handler)
+{
+       AUTOLOCK(release_lock);
+       channel_handler_release_list.push_back(handler);
+}
+
 class terminator : public event_handler
 {
 public:
@@ -234,7 +281,7 @@ public:
        : m_loop(loop)
        { }
 
-       bool handle(int fd, event_condition condition)
+       bool handle(int fd, event_condition condition, void **data)
        {
                m_loop->terminate();
                return false;
index 735badb602180846fc2841fbee3ab3a6e61f74a5..aeae959c36f1ea89d358504155be8728fe0decd0 100644 (file)
@@ -30,6 +30,9 @@
 
 namespace ipc {
 
+class channel;
+class channel_handler;
+
 enum event_condition_e {
        EVENT_IN =  G_IO_IN,
        EVENT_OUT = G_IO_OUT,
@@ -80,9 +83,11 @@ public:
 
        bool remove_event(uint64_t id);
        void remove_all_events(void);
-
        void release_info(handler_info *info);
 
+       void add_channel_release_queue(channel *ch);
+       void add_channel_handler_release_list(channel_handler *handler);
+
        bool run(int timeout = 0);
        void stop(void);
        void terminate(void);