Reviewed-by: Jan Friesse <[email protected]> Angus Salkeld napsal(a): > If we get EMFILE from accept() then withdraw the published > server listening socket. Then when a connection closes > see if we need to re-publish the server sockect. > > Signed-off-by: Angus Salkeld <[email protected]> > --- > exec/ipc.c | 161 +++++++++++++++++++++++++++++++++++++---------------------- > 1 files changed, 101 insertions(+), 60 deletions(-) > > diff --git a/exec/ipc.c b/exec/ipc.c > index 5337d25..17520c7 100644 > --- a/exec/ipc.c > +++ b/exec/ipc.c > @@ -98,6 +98,21 @@ > #define MSG_SEND_LOCKED 0 > #define MSG_SEND_UNLOCKED 1 > > +#if defined(OPENAIS_LINUX) || defined(OPENAIS_SOLARIS) > +/* SUN_LEN is broken for abstract namespace > + */ > +#define AIS_SUN_LEN(a) sizeof(*(a)) > +#else > +#define AIS_SUN_LEN(a) SUN_LEN(a) > +#endif > + > +static int libais_server_fd = -1; > +#if defined(OPENAIS_LINUX) > +char *socketname = "libais.socket"; > +#else > +char *socketname = "/var/run/libais.socket"; > +#endif > + > static unsigned int g_gid_valid = 0; > > static void (*ipc_serialize_lock_fn) (void); > @@ -161,6 +176,9 @@ static int priv_change (struct conn_info *conn_info); > > static void ipc_disconnect (struct conn_info *conn_info); > > +static int poll_handler_accept (poll_handle handle, int fd, > + int revent, void *data); > + > static int ipc_thread_active (void *conn) > { > struct conn_info *conn_info = (struct conn_info *)conn; > @@ -190,6 +208,78 @@ static int ipc_thread_exiting (void *conn) > return (retval); > } > > + > +static void publish_server_socket(void) > +{ > + int32_t res = 0; > + struct sockaddr_un un_addr; > + > + if (libais_server_fd != -1) { > + return; > + } > + log_printf (LOG_LEVEL_WARNING, > + "Publishing socket for client connections.\n"); > + > + /* > + * Create socket for libais clients, name socket, listen for connections > + */ > + libais_server_fd = socket (PF_UNIX, SOCK_STREAM, 0); > + if (libais_server_fd == -1) { > + log_printf (LOG_LEVEL_ERROR, > + "Cannot create libais client connections socket.\n"); > + openais_shutdown (AIS_DONE_LIBAIS_SOCKET); > + }; > + > + totemip_nosigpipe (libais_server_fd); > + res = fcntl (libais_server_fd, F_SETFL, O_NONBLOCK); > + if (res == -1) { > + log_printf (LOG_LEVEL_ERROR, > + "Could not set non-blocking operation on server socket: > %s\n", > + strerror (errno)); > + openais_shutdown (AIS_DONE_LIBAIS_SOCKET); > + } > + > +#if !defined(OPENAIS_LINUX) > + unlink(socketname); > +#endif > + memset (&un_addr, 0, sizeof (struct sockaddr_un)); > + un_addr.sun_family = AF_UNIX; > +#if defined(OPENAIS_BSD) || defined(OPENAIS_DARWIN) > + un_addr.sun_len = sizeof(struct sockaddr_un); > +#endif > +#if defined(OPENAIS_LINUX) > + strcpy (un_addr.sun_path + 1, socketname); > +#else > + strcpy (un_addr.sun_path, socketname); > +#endif > + > + res = bind (libais_server_fd, (struct sockaddr *)&un_addr, > AIS_SUN_LEN(&un_addr)); > + if (res) { > + log_printf (LOG_LEVEL_ERROR, > + "ERROR: Could not bind AF_UNIX: %s.\n", > + strerror (errno)); > + openais_shutdown (AIS_DONE_LIBAIS_BIND); > + } > + listen (libais_server_fd, SERVER_BACKLOG); > + > + /* > + * Setup libais connection dispatch routine > + */ > + poll_dispatch_add (aisexec_poll_handle, libais_server_fd, > + POLLIN|POLLNVAL, 0, poll_handler_accept); > +} > + > +static void withdraw_server_socket(void) > +{ > + log_printf (LOG_LEVEL_WARNING, > + "Withdrawing socket for client connections.\n"); > + > + poll_dispatch_delete (aisexec_poll_handle, libais_server_fd); > + shutdown(libais_server_fd, SHUT_RDWR); > + close(libais_server_fd); > + libais_server_fd = -1; > +} > + > /* > * returns 0 if should be called again, -1 if finished > */ > @@ -211,6 +301,7 @@ static inline int conn_info_destroy (struct conn_info > *conn_info) > conn_info->state == CONN_STATE_DISCONNECT_INACTIVE) { > list_del (&conn_info->list); > close (conn_info->fd); > + publish_server_socket(); > free (conn_info); > return (-1); > } > @@ -257,6 +348,7 @@ static inline int conn_info_destroy (struct conn_info > *conn_info) > free (conn_info->private_data); > } > close (conn_info->fd); > + publish_server_socket(); > free (conn_info); > ipc_serialize_unlock_fn(); > return (-1); > @@ -736,19 +828,6 @@ static int conn_info_create (int fd) > return (0); > } > > -#if defined(OPENAIS_LINUX) || defined(OPENAIS_SOLARIS) > -/* SUN_LEN is broken for abstract namespace > - */ > -#define AIS_SUN_LEN(a) sizeof(*(a)) > -#else > -#define AIS_SUN_LEN(a) SUN_LEN(a) > -#endif > - > -#if defined(OPENAIS_LINUX) > -char *socketname = "libais.socket"; > -#else > -char *socketname = "/var/run/libais.socket"; > -#endif > > static int poll_handler_accept ( > poll_handle handle, > @@ -773,7 +852,12 @@ retry_accept: > } > > if (new_fd == -1) { > - log_printf (LOG_LEVEL_ERROR, "ERROR: Could not accept Library > connection: %s\n", strerror (errno)); > + log_printf (LOG_LEVEL_ERROR, > + "ERROR: Could not accept Library connection: %s\n", > + strerror (errno)); > + if (errno == EMFILE || errno == ENFILE) { > + withdraw_server_socket(); > + } > return (0); /* This is an error, but -1 would indicate > disconnect from poll loop */ > } > > @@ -830,61 +914,18 @@ void message_source_set ( > source->conn = conn; > } > > + > + > void openais_ipc_init ( > unsigned int gid_valid, > void (*serialize_lock_fn) (void), > void (*serialize_unlock_fn) (void)) > { > - 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 > - */ > - libais_server_fd = socket (PF_UNIX, SOCK_STREAM, 0); > - if (libais_server_fd == -1) { > - log_printf (LOG_LEVEL_ERROR ,"Cannot create libais client > connections socket.\n"); > - openais_shutdown (AIS_DONE_LIBAIS_SOCKET); > - }; > - > - totemip_nosigpipe (libais_server_fd); > - res = fcntl (libais_server_fd, F_SETFL, O_NONBLOCK); > - if (res == -1) { > - log_printf (LOG_LEVEL_ERROR, "Could not set non-blocking > operation on server socket: %s\n", strerror (errno)); > - openais_shutdown (AIS_DONE_LIBAIS_SOCKET); > - } > - > -#if !defined(OPENAIS_LINUX) > - unlink(socketname); > -#endif > - memset (&un_addr, 0, sizeof (struct sockaddr_un)); > - un_addr.sun_family = AF_UNIX; > -#if defined(OPENAIS_BSD) || defined(OPENAIS_DARWIN) > - un_addr.sun_len = sizeof(struct sockaddr_un); > -#endif > -#if defined(OPENAIS_LINUX) > - strcpy (un_addr.sun_path + 1, socketname); > -#else > - strcpy (un_addr.sun_path, socketname); > -#endif > - > - res = bind (libais_server_fd, (struct sockaddr *)&un_addr, > AIS_SUN_LEN(&un_addr)); > - if (res) { > - log_printf (LOG_LEVEL_ERROR, "ERROR: Could not bind AF_UNIX: > %s.\n", strerror (errno)); > - openais_shutdown (AIS_DONE_LIBAIS_BIND); > - } > - listen (libais_server_fd, SERVER_BACKLOG); > - > - /* > - * Setup libais connection dispatch routine > - */ > - poll_dispatch_add (aisexec_poll_handle, libais_server_fd, > - POLLIN|POLLNVAL, 0, poll_handler_accept); > + publish_server_socket(); > > g_gid_valid = gid_valid; > }
_______________________________________________ Openais mailing list [email protected] https://lists.linux-foundation.org/mailman/listinfo/openais
