It fixes segmentation fault in client.
Change-Id: I15977d8189b68b5ff7e319eb344ad9ebd5e9ad80
Signed-off-by: TaeminYeom <taemin.yeom@samsung.com>
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();
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;
#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;
};
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();
void sensor_listener::restore(void)
{
- ret_if(!is_connected());
+ if (lock.try_lock())
+ return;
m_cmd_channel->disconnect();
delete m_cmd_channel;
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)
_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();
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)
#include <event_loop.h>
#include <sensor_info.h>
#include <sensor_types.h>
+#include <cmutex.h>
#include <map>
#include <atomic>
#include <vector>
std::atomic<bool> m_started;
std::map<int, int> m_attributes_int;
std::map<int, std::vector<char>> m_attributes_str;
+
+ cmutex lock;
};
}
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;
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;
}
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 */
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) */
}
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)
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)
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;
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();
}
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;
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);
{
}
-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);
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;
}
}
- bool handle(int fd, event_condition condition)
+ bool handle(int fd, event_condition condition, void** data)
{
if (!m_ch) {
return false;
: m_ch(ch)
{ }
- bool handle(int fd, event_condition condition)
+ bool handle(int fd, event_condition condition, void **data)
{
if (!m_ch) {
return false;
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;
/* 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);
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';
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;
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;
}
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);
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;
class channel;
class message;
+class channel_handler;
class channel_handler {
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;
};
}
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);
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);
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;
#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;
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)
/* _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:
: m_loop(loop)
{ }
- bool handle(int fd, event_condition condition)
+ bool handle(int fd, event_condition condition, void **data)
{
m_loop->terminate();
return false;
namespace ipc {
+class channel;
+class channel_handler;
+
enum event_condition_e {
EVENT_IN = G_IO_IN,
EVENT_OUT = G_IO_OUT,
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);