From a68b9f394414239f869c1f7dcabec8a414c5865d Mon Sep 17 00:00:00 2001 From: Steven Dake Date: Wed, 25 Feb 2009 04:55:32 +0000 Subject: [PATCH] Fix possible segfault with IPC service. git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@1779 fd59a12c-fef9-0310-b244-a6a79926bd2f --- exec/ipc.c | 70 ++++++++++++++++++++++++++--------------------------- exec/ipc.h | 2 -- exec/main.c | 2 +- 3 files changed, 35 insertions(+), 39 deletions(-) diff --git a/exec/ipc.c b/exec/ipc.c index cb012081..9647743f 100644 --- a/exec/ipc.c +++ b/exec/ipc.c @@ -102,10 +102,6 @@ LOGSYS_DECLARE_SUBSYS ("IPC", LOG_INFO); static unsigned int g_gid_valid = 0; -static void (*ipc_serialize_lock_fn) (void); - -static void (*ipc_serialize_unlock_fn) (void); - DECLARE_LIST_INIT (conn_info_list_head); struct outq_item { @@ -155,11 +151,25 @@ static int priv_change (struct conn_info *conn_info); static void ipc_disconnect (struct conn_info *conn_info); +static int ipc_conn_exiting (void *conn) +{ + struct conn_info *conn_info = (struct conn_info *)conn; + + pthread_mutex_lock (&conn_info->mutex); + if (conn_info->destroyed || conn_info->disconnect_requested) { + pthread_mutex_unlock (&conn_info->mutex); + return (1); + } + pthread_mutex_unlock (&conn_info->mutex); + return (0); +} + + static inline int conn_info_destroy (struct conn_info *conn_info) { - unsigned int res; +unsigned int res; - list_del (&conn_info->list); +list_del (&conn_info->list); list_init (&conn_info->list); if (conn_info->service == SOCKET_SERVICE_INIT) { @@ -168,15 +178,9 @@ static inline int conn_info_destroy (struct conn_info *conn_info) free (conn_info); return (0); } - /* - * Destroy shared memory segment and semaphore - */ if (conn_info->destroyed == 0) { - cs_conn_refcount_dec (conn_info); - shmdt (conn_info->mem); - res = shmctl (conn_info->shmid, IPC_RMID, NULL); - semctl (conn_info->semid, 0, IPC_RMID); conn_info->destroyed = 1; + cs_conn_refcount_dec (conn_info); } pthread_mutex_lock (&conn_info->mutex); @@ -194,6 +198,13 @@ static inline int conn_info_destroy (struct conn_info *conn_info) return (-1); } + /* + * Destroy shared memory segment and semaphore + */ + shmdt (conn_info->mem); + res = shmctl (conn_info->shmid, IPC_RMID, NULL); + semctl (conn_info->semid, 0, IPC_RMID); + /* * Free allocated data needed to retry exiting library IPC connection */ @@ -227,22 +238,19 @@ static void *pthread_ipc_consumer (void *conn) sop.sem_op = -1; sop.sem_flg = 0; retry_semop: + if (ipc_conn_exiting (conn_info)) { + pthread_exit (0); + } res = semop (conn_info->semid, &sop, 1); if ((res == -1) && (errno == EINTR || errno == EAGAIN)) { goto retry_semop; } else if ((res == -1) && (errno == EINVAL || errno == EIDRM)) { - cs_conn_refcount_dec (conn); - return (0); - } - if (conn_info->destroyed || conn_info->disconnect_requested) { - break; + pthread_exit (0); } header = (mar_req_header_t *)conn_info->mem->req_buffer; - ipc_serialize_lock_fn (); - send_ok_joined_iovec.iov_base = (char *)header; send_ok_joined_iovec.iov_len = header->size; send_ok_joined = totempg_groups_send_ok_joined (corosync_group_handle, @@ -269,8 +277,6 @@ retry_semop: cs_response_send (conn_info, &res_overlay, res_overlay.header.size); } - - ipc_serialize_unlock_fn (); } cs_conn_refcount_dec (conn); return (NULL); @@ -443,7 +449,7 @@ static int poll_handler_connection ( /* * If an error occurs, try to exit if possible */ - if ((conn_info->disconnect_requested) || (revent & (POLLERR|POLLHUP))) { + if (ipc_conn_exiting (conn_info) || (revent & (POLLERR|POLLHUP))) { return poll_handler_connection_destroy (conn_info); } @@ -489,7 +495,6 @@ static int poll_handler_connection ( conn_info->semid = semget (conn_info->semkey, 3, 0600); conn_info->pending_semops = 0; conn_info->refcount = 1; - cs_conn_refcount_inc (conn_info); conn_info->private_data = malloc (ais_service[conn_info->service]->private_data_size); memset (conn_info->private_data, 0, @@ -522,6 +527,7 @@ static int poll_handler_connection ( } } else if (revent & POLLIN) { + cs_conn_refcount_inc (conn_info); res = recv (fd, &buf, 1, MSG_NOSIGNAL); if (res == 1) { switch (buf) { @@ -545,9 +551,11 @@ static int poll_handler_connection ( if (res == 0) { return poll_handler_connection_destroy (conn_info); } + cs_conn_refcount_dec (conn_info); #endif } + cs_conn_refcount_inc (conn_info); pthread_mutex_lock (&conn_info->mutex); if ((conn_info->disconnect_requested == 0) && (revent & POLLOUT)) { buf = !list_empty (&conn_info->outq_head); @@ -575,8 +583,7 @@ static int poll_handler_connection ( } } pthread_mutex_unlock (&conn_info->mutex); - - return (0); + cs_conn_refcount_dec (conn_info); } static void ipc_disconnect (struct conn_info *conn_info) @@ -706,18 +713,12 @@ void message_source_set ( } extern void cs_ipc_init ( - void (*serialize_lock_fn) (void), - void (*serialize_unlock_fn) (void), unsigned int gid_valid) { int libais_server_fd; struct sockaddr_un un_addr; int res; - ipc_serialize_lock_fn = serialize_lock_fn; - ipc_serialize_unlock_fn = serialize_unlock_fn; - - /* * Create socket for libais clients, name socket, listen for connections */ @@ -1014,12 +1015,9 @@ static void msg_send_or_queue (void *conn, struct iovec *iov, int iov_len) /* * Exit transmission if the connection is dead */ - pthread_mutex_lock (&conn_info->mutex); - if (conn_info->destroyed || conn_info->disconnect_requested) { - pthread_mutex_unlock (&conn_info->mutex); + if (ipc_conn_exiting (conn)) { return; } - pthread_mutex_unlock (&conn_info->mutex); bytes_left = shared_mem_dispatch_bytes_left (conn_info); for (i = 0; i < iov_len; i++) { diff --git a/exec/ipc.h b/exec/ipc.h index 0a231ec2..c5aad554 100644 --- a/exec/ipc.h +++ b/exec/ipc.h @@ -40,8 +40,6 @@ extern void message_source_set (mar_message_source_t *source, void *conn); extern int message_source_is_local (mar_message_source_t *source); extern void cs_ipc_init ( - void (*serialize_lock_fn) (void), - void (*serialize_unlock_fn) (void), unsigned int gid_valid); extern void *cs_conn_private_data_get (void *conn); diff --git a/exec/main.c b/exec/main.c index 8fe095e5..98a1fe09 100644 --- a/exec/main.c +++ b/exec/main.c @@ -684,7 +684,7 @@ int main (int argc, char **argv) aisexec_mempool_init (); - cs_ipc_init (serialize_mutex_lock, serialize_mutex_unlock, main_config.gid); + cs_ipc_init (main_config.gid); /* * Start main processing loop