From b64f00d374be7a878d308cabf2e8c1a3929e08df Mon Sep 17 00:00:00 2001 From: Suchang Woo Date: Thu, 10 Sep 2015 20:26:42 +0900 Subject: [PATCH] library: add client mutex lock for multi-thread For multi-thread, a mutex lock is added to the client library. This patch is workaround. Because a function protected by a lock can be reentered in a callback function. To prevent dead-lock, a mutex lock should be unlocked when it calls a callback function. Change-Id: Ic40a6ba0715c5f9bd9f24bc7fd03bc23f1f9519e --- lib/buxton2.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/lib/buxton2.c b/lib/buxton2.c index a7933f6..fe3e17a 100644 --- a/lib/buxton2.c +++ b/lib/buxton2.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -89,6 +90,7 @@ struct buxton_client { }; static GList *clients; /* data: buxton_client */ +static pthread_mutex_t clients_lock = PTHREAD_MUTEX_INITIALIZER; static guint32 client_msgid; static struct buxton_value *value_create(enum buxton_key_type type, void *value) @@ -643,6 +645,8 @@ static void proc_msg_cb(void *user_data, assert(client); + pthread_mutex_unlock(&clients_lock); + switch (type) { case MSG_NOTI: proc_msg_noti(client, data, len); @@ -664,13 +668,27 @@ static void proc_msg_cb(void *user_data, bxt_err("proc msg: unknown message type %d", type); break; } + + pthread_mutex_lock(&clients_lock); } static int proc_msg(struct buxton_client *client) { int r; + GList *f; + + assert(client); + + pthread_mutex_lock(&clients_lock); + f = g_list_find(clients, client); + if (!f) { + bxt_dbg("recv msg: cli %p removed\n", client); + pthread_mutex_unlock(&clients_lock); + return 0; + } r = proto_recv_async(client->fd, proc_msg_cb, client); + pthread_mutex_unlock(&clients_lock); if (r == -1) { bxt_err("recv msg: fd %d errno %d", client->fd, errno); return -1; @@ -1852,11 +1870,22 @@ static void free_noti(struct bxt_noti *noti) static gboolean close_conn(gpointer data) { struct buxton_client *cli = data; + GList *f; assert(cli); - if (cli->fd == -1) + pthread_mutex_lock(&clients_lock); + f = g_list_find(clients, cli); + if (!f) { + bxt_dbg("%s: cli %p removed\n", __func__, cli); + pthread_mutex_unlock(&clients_lock); return G_SOURCE_REMOVE; + } + + if (cli->fd == -1) { + pthread_mutex_unlock(&clients_lock); + return G_SOURCE_REMOVE; + } if (cli->fd_id) { g_source_remove(cli->fd_id); @@ -1865,6 +1894,7 @@ static gboolean close_conn(gpointer data) close(cli->fd); cli->fd = -1; + pthread_mutex_unlock(&clients_lock); if (cli->st_callback) cli->st_callback(BUXTON_STATUS_DISCONNECTED, cli->st_data); @@ -1878,6 +1908,7 @@ static void free_client(struct buxton_client *cli) close_conn(cli); + pthread_mutex_lock(&clients_lock); clients = g_list_remove(clients, cli); if (cli->req_cbs) @@ -1887,6 +1918,7 @@ static void free_client(struct buxton_client *cli) g_hash_table_destroy(cli->noti_cbs); free(cli); + pthread_mutex_unlock(&clients_lock); } int connect_server(const char *addr) @@ -1927,9 +1959,18 @@ static gboolean recv_cb(gint fd, GIOCondition cond, gpointer data) { struct buxton_client *cli = data; int r; + GList *f; assert(cli); + pthread_mutex_lock(&clients_lock); + f = g_list_find(clients, cli); + if (!f) { + bxt_dbg("recv %d: cli %p removed\n", fd, cli); + pthread_mutex_unlock(&clients_lock); + return G_SOURCE_CONTINUE; + } + bxt_dbg("recv %d: cond %x", fd, cond); if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) { @@ -1937,8 +1978,10 @@ static gboolean recv_cb(gint fd, GIOCondition cond, gpointer data) cli->fd_id = 0; g_idle_add(close_conn, cli); + pthread_mutex_unlock(&clients_lock); return G_SOURCE_REMOVE; } + pthread_mutex_unlock(&clients_lock); r = proc_msg(cli); if (r == -1) { @@ -2014,7 +2057,9 @@ EXPORT int buxton_open(struct buxton_client **client, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, recv_cb, cli); + pthread_mutex_lock(&clients_lock); clients = g_list_append(clients, cli); + pthread_mutex_unlock(&clients_lock); *client = cli; if (callback) -- 2.7.4