The model is when server has too many sockets in use, library returns 
TRY_AGAIN?

Regards
-steve

On 08/08/2010 08:01 PM, Angus Salkeld wrote:
>   Whenever we accept a new connection or close an
>   existing one, check the number of available file
>   descriptors and either publish or withdraw the
>   IPC listening socket.
>
> Signed-off-by: Angus Salkeld<[email protected]>
> ---
>   exec/ipc.c |   92 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
>   1 files changed, 86 insertions(+), 6 deletions(-)
>
> diff --git a/exec/ipc.c b/exec/ipc.c
> index 5337d25..bf3102c 100644
> --- a/exec/ipc.c
> +++ b/exec/ipc.c
> @@ -99,6 +99,7 @@
>   #define MSG_SEND_UNLOCKED   1
>
>   static unsigned int g_gid_valid = 0;
> +static int32_t libais_server_fd = -1;
>
>   static void (*ipc_serialize_lock_fn) (void);
>
> @@ -161,6 +162,15 @@ static int priv_change (struct conn_info *conn_info);
>
>   static void ipc_disconnect (struct conn_info *conn_info);
>
> +static void server_socket_publish(void);
> +
> +static void server_socket_withdraw(void);
> +
> +static void server_socket_check(void);
> +
> +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;
> @@ -211,6 +221,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);
> +             server_socket_check();
>               free (conn_info);
>               return (-1);
>       }
> @@ -257,6 +268,7 @@ static inline int conn_info_destroy (struct conn_info 
> *conn_info)
>               free (conn_info->private_data);
>       }
>       close (conn_info->fd);
> +     server_socket_check();
>       free (conn_info);
>       ipc_serialize_unlock_fn();
>       return (-1);
> @@ -773,7 +785,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) {
> +                     server_socket_withdraw();
> +             }
>               return (0); /* This is an error, but -1 would indicate 
> disconnect from poll loop */
>       }
>
> @@ -802,6 +819,7 @@ retry_accept:
>       if (res != 0) {
>               close (new_fd);
>       }
> +     server_socket_check();
>
>       return (0);
>   }
> @@ -835,14 +853,23 @@ void openais_ipc_init (
>       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;
>
> +     server_socket_publish();
> +
> +     g_gid_valid = gid_valid;
> +}
> +
> +static void server_socket_publish(void)
> +{
> +     int32_t res = 0;
> +     struct sockaddr_un un_addr;
> +
> +     log_printf(LOG_LEVEL_WARNING,
> +             "Publishing socket for client connections.\n");
> +
>       /*
>        * Create socket for libais clients, name socket, listen for connections
>        */
> @@ -885,8 +912,61 @@ void openais_ipc_init (
>            */
>           poll_dispatch_add (aisexec_poll_handle, libais_server_fd,
>                   POLLIN|POLLNVAL, 0, poll_handler_accept);
> +}
>
> -     g_gid_valid = gid_valid;
> +static void server_socket_withdraw(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;
> +}
> +
> +/*
> + * The actual used sockets is 12 but allowing a larger number
> + * for safety.
> + */
> +#define COROIPC_NUM_RESERVED_SOCKETS 25
> +
> +static int32_t num_avail_sockets(void)
> +{
> +     struct rlimit lim;
> +     int32_t open_socks = 0;
> +     int32_t res;
> +     struct list_head *list;
> +
> +     if (getrlimit(RLIMIT_NOFILE,&lim) == -1) {
> +             char error_str[100];
> +             strerror_r(errno, error_str, 100);
> +             log_printf(LOG_LEVEL_ERROR,
> +                     "getrlimit: %s\n", error_str);
> +             return -1;
> +     }
> +
> +     for (list = conn_info_list_head.next; list !=&conn_info_list_head;
> +             list = list->next) {
> +             open_socks++;
> +     }
> +     res = lim.rlim_cur - (open_socks + COROIPC_NUM_RESERVED_SOCKETS);
> +     log_printf(LOG_LEVEL_DEBUG,
> +             "(lim.rlim_cur:%lu - (open_socks:%d + reserved:%d) == %d\n",
> +             lim.rlim_cur, open_socks, COROIPC_NUM_RESERVED_SOCKETS, res);
> +     return res;
> +}
> +
> +static void server_socket_check(void)
> +{
> +     int32_t num = num_avail_sockets();
> +
> +     if (libais_server_fd == -1&&  num>  0) {
> +             server_socket_publish();
> +     }
> +     else if (libais_server_fd != -1&&  num<= 0) {
> +             server_socket_withdraw();
> +     }
>   }
>
>   void openais_ipc_exit (void)

_______________________________________________
Openais mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/openais

Reply via email to