From: Saverio Proto Date: Mon, 2 Jun 2014 11:54:47 +0000 (+0200) Subject: Provide thread-safety to functions that return pointers to meshlink_node_t. X-Git-Url: https://git.meshlink.io/?a=commitdiff_plain;h=391a8674fcd886165dc02154d3ef0d3377f2c840;p=meshlink Provide thread-safety to functions that return pointers to meshlink_node_t. - The mesh->nodes tree can be updated by the library thread at any time, so it must be protected by a mutex or rwlock. --- diff --git a/src/meshlink.c b/src/meshlink.c index 72e27b0f..fc8408ad 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -735,6 +735,7 @@ meshlink_handle_t *meshlink_open(const char *confbase, const char *name) { mesh->confbase = xstrdup(confbase); mesh->name = xstrdup(name); pthread_mutex_init ( &(mesh->outpacketqueue_mutex), NULL); + pthread_mutex_init ( &(mesh->nodes_mutex), NULL); event_loop_init(&mesh->loop); mesh->loop.data = mesh; @@ -898,12 +899,17 @@ meshlink_node_t *meshlink_get_node(meshlink_handle_t *mesh, const char *name) { size_t meshlink_get_all_nodes(meshlink_handle_t *mesh, meshlink_node_t **nodes, size_t nmemb) { size_t i = 0; + //lock mesh->nodes + pthread_mutex_lock(&(mesh->nodes_mutex)); + for splay_each(node_t, n, mesh->nodes) { if(i < nmemb) nodes[i] = (meshlink_node_t *)n; i++; } + pthread_mutex_unlock(&(mesh->nodes_mutex)); + return i; } diff --git a/src/meshlink_internal.h b/src/meshlink_internal.h index c58c4773..cb60416d 100644 --- a/src/meshlink_internal.h +++ b/src/meshlink_internal.h @@ -61,6 +61,7 @@ struct meshlink_handle { pthread_t thread; pthread_mutex_t outpacketqueue_mutex; + pthread_mutex_t nodes_mutex; event_loop_t loop; listen_socket_t listen_socket[MAXSOCKETS]; int listen_sockets; diff --git a/src/node.c b/src/node.c index 3e4dec95..0a7b4a52 100644 --- a/src/node.c +++ b/src/node.c @@ -36,13 +36,17 @@ static int node_compare(const node_t *a, const node_t *b) { } void init_nodes(meshlink_handle_t *mesh) { + pthread_mutex_lock(&(mesh->nodes_mutex)); mesh->nodes = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node); node_udp_cache = hash_alloc(0x100, sizeof(sockaddr_t)); + pthread_mutex_unlock(&(mesh->nodes_mutex)); } void exit_nodes(meshlink_handle_t *mesh) { + pthread_mutex_lock(&(mesh->nodes_mutex)); hash_free(node_udp_cache); splay_delete_tree(mesh->nodes); + pthread_mutex_unlock(&(mesh->nodes_mutex)); } node_t *new_node(void) { @@ -81,25 +85,34 @@ void free_node(node_t *n) { } void node_add(meshlink_handle_t *mesh, node_t *n) { + pthread_mutex_lock(&(mesh->nodes_mutex)); n->mesh = mesh; splay_insert(mesh->nodes, n); + pthread_mutex_unlock(&(mesh->nodes_mutex)); } void node_del(meshlink_handle_t *mesh, node_t *n) { + pthread_mutex_lock(&(mesh->nodes_mutex)); timeout_del(&mesh->loop, &n->mtutimeout); for splay_each(edge_t, e, n->edge_tree) edge_del(mesh, e); splay_delete(mesh->nodes, n); + pthread_mutex_unlock(&(mesh->nodes_mutex)); } node_t *lookup_node(meshlink_handle_t *mesh, char *name) { node_t n = {NULL}; + node_t* result; n.name = name; - return splay_search(mesh->nodes, &n); + pthread_mutex_lock(&(mesh->nodes_mutex)); + result = splay_search(mesh->nodes, &n); + pthread_mutex_unlock(&(mesh->nodes_mutex)); + + return result; } node_t *lookup_node_udp(meshlink_handle_t *mesh, const sockaddr_t *sa) {