From 0f5c35260be47064b275b560f759d8ec2145b9b6 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 12 May 2015 07:47:32 -0600 Subject: [PATCH] Local sockets: Local stream sockets had problem of double releasing pipes (both server and client attempt release), which causes wrong pipe pair being closed in multi-client case. Solve by adding per connection instance ID to pipe names. From Jussi Kivilinna (2015-05-12). --- net/local/local.h | 2 ++ net/local/local_accept.c | 1 + net/local/local_bind.c | 1 + net/local/local_connect.c | 21 +++++++++++++++++++++ net/local/local_fifo.c | 26 ++++++++++++++++++++++---- 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/net/local/local.h b/net/local/local.h index 5378d19b84..999f804ea0 100644 --- a/net/local/local.h +++ b/net/local/local.h @@ -143,6 +143,8 @@ struct local_conn_s int16_t lc_infd; /* File descriptor of read-only FIFO (peers) */ int16_t lc_outfd; /* File descriptor of write-only FIFO (peers) */ char lc_path[UNIX_PATH_MAX]; /* Path assigned by bind() */ + int32_t lc_instance_id; /* Connection instance ID for stream + * server<->client connection pair */ #ifdef CONFIG_NET_LOCAL_STREAM /* SOCK_STREAM fields common to both client and server */ diff --git a/net/local/local_accept.c b/net/local/local_accept.c index 59ab57145f..00eaf0da3b 100644 --- a/net/local/local_accept.c +++ b/net/local/local_accept.c @@ -170,6 +170,7 @@ int psock_local_accept(FAR struct socket *psock, FAR struct sockaddr *addr, strncpy(conn->lc_path, client->lc_path, UNIX_PATH_MAX-1); conn->lc_path[UNIX_PATH_MAX-1] = '\0'; + conn->lc_instance_id = client->lc_instance_id; /* Open the server-side write-only FIFO. This should not * block. diff --git a/net/local/local_bind.c b/net/local/local_bind.c index 675b495163..316fe3e2e9 100644 --- a/net/local/local_bind.c +++ b/net/local/local_bind.c @@ -109,6 +109,7 @@ int psock_local_bind(FAR struct socket *psock, (void)strncpy(conn->lc_path, unaddr->sun_path, UNIX_PATH_MAX-1); conn->lc_path[UNIX_PATH_MAX-1] = '\0'; + conn->lc_instance_id = -1; } } diff --git a/net/local/local_connect.c b/net/local/local_connect.c index 714afe1838..99ea989edf 100644 --- a/net/local/local_connect.c +++ b/net/local/local_connect.c @@ -59,6 +59,26 @@ * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: local_generate_instance_id + ****************************************************************************/ + +static int32_t local_generate_instance_id(void) +{ + static int32_t g_next_instance_id = 0; + int32_t id; + + /* Called from local_connect with net_lock held. */ + + id = g_next_instance_id++; + if (g_next_instance_id < 0) + { + g_next_instance_id = 0; + } + + return id; +} + /**************************************************************************** * Name: _local_semtake() and _local_semgive() * @@ -286,6 +306,7 @@ int psock_local_connect(FAR struct socket *psock, client->lc_proto = conn->lc_proto; strncpy(client->lc_path, unaddr->sun_path, UNIX_PATH_MAX-1); client->lc_path[UNIX_PATH_MAX-1] = '\0'; + client->lc_instance_id = local_generate_instance_id(); /* The client is now bound to an address */ diff --git a/net/local/local_fifo.c b/net/local/local_fifo.c index 2d00f8caba..0e4b3d667c 100644 --- a/net/local/local_fifo.c +++ b/net/local/local_fifo.c @@ -80,8 +80,17 @@ static inline void local_cs_name(FAR struct local_conn_s *conn, FAR char *path) { - (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_CS_SUFFIX, - conn->lc_path); + if (conn->lc_instance_id < 0) + { + (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_CS_SUFFIX, + conn->lc_path); + } + else + { + (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_CS_SUFFIX "%x", + conn->lc_path, conn->lc_instance_id); + } + path[LOCAL_FULLPATH_LEN-1] = '\0'; } #endif /* CONFIG_NET_LOCAL_STREAM */ @@ -98,8 +107,17 @@ static inline void local_cs_name(FAR struct local_conn_s *conn, static inline void local_sc_name(FAR struct local_conn_s *conn, FAR char *path) { - (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_SC_SUFFIX, - conn->lc_path); + if (conn->lc_instance_id < 0) + { + (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_SC_SUFFIX, + conn->lc_path); + } + else + { + (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_SC_SUFFIX "%x", + conn->lc_path, conn->lc_instance_id); + } + path[LOCAL_FULLPATH_LEN-1] = '\0'; } #endif /* CONFIG_NET_LOCAL_STREAM */