From cca3d15b90b5fae067a4cf5b7dbf13dcb0f25721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Sat, 1 Dec 2018 21:31:32 +0200 Subject: [PATCH] MXS-2196: Simplify client accept code The code that waited for some time if a system resource limit was reached made the lower level code more complex than it should be. If such a situation would be encountered, it is unlikely that the code would make a noticeable difference. Also renamed the functions to better represent what they do. --- server/core/listener.cc | 92 +++++++---------------------------------- 1 file changed, 14 insertions(+), 78 deletions(-) diff --git a/server/core/listener.cc b/server/core/listener.cc index 463ac4079..ea1e082a5 100644 --- a/server/core/listener.cc +++ b/server/core/listener.cc @@ -830,106 +830,42 @@ int start_listening(const char* config) /** - * @brief Accept a new client connection, given listener, return file descriptor - * - * Up to 10 retries will be attempted in case of non-permanent errors. Calls - * the accept function and analyses the return, logging any errors and making - * an appropriate return. + * @brief Accept a new client connection * * @param fd File descriptor to accept from * @param client_conn Output where connection information is stored * * @return -1 for failure, or a file descriptor for the new connection */ -static int dcb_accept_one_connection(int fd, struct sockaddr* client_conn) +static int accept_one_connection(int fd, struct sockaddr* client_conn) { - int c_sock; + socklen_t client_len = sizeof(struct sockaddr_storage); - /* Try up to 10 times to get a file descriptor by use of accept */ - for (int i = 0; i < 10; i++) + /* new connection from client */ + int client_fd = accept(fd, client_conn, &client_len); + + if (client_fd == -1 && errno != EAGAIN && errno != EWOULDBLOCK) { - socklen_t client_len = sizeof(struct sockaddr_storage); - int eno = 0; - - /* new connection from client */ - c_sock = accept(fd, client_conn, &client_len); - eno = errno; - errno = 0; - - if (c_sock == -1) - { - /* Did not get a file descriptor */ - if (eno == EAGAIN || eno == EWOULDBLOCK) - { - /** - * We have processed all incoming connections, break out - * of loop for return of -1. - */ - break; - } - else if (eno == ENFILE || eno == EMFILE) - { - struct timespec ts1; - long long nanosecs; - - /** - * Exceeded system's (ENFILE) or processes - * (EMFILE) max. number of files limit. - */ - - /* Log an error the first time this happens */ - if (i == 0) - { - MXS_ERROR("Failed to accept new client connection: %d, %s", - eno, - mxs_strerror(eno)); - } - nanosecs = (long long)1000000 * 100 * i * i; - ts1.tv_sec = nanosecs / 1000000000; - ts1.tv_nsec = nanosecs % 1000000000; - nanosleep(&ts1, NULL); - - /* Remain in loop for up to the loop limit, retries. */ - } - else - { - /** - * Other error, log it then break out of loop for return of -1. - */ - MXS_ERROR("Failed to accept new client connection: %d, %s", - eno, - mxs_strerror(eno)); - break; - } - } - else - { - break; - } + MXS_ERROR("Failed to accept new client connection: %d, %s", errno, mxs_strerror(errno)); } - return c_sock; + + return client_fd; } /** - * @brief Accept a new client connection, given a listener, return new DCB - * - * Calls dcb_accept_one_connection to do the basic work of obtaining a new - * connection from a listener. If that succeeds, some settings are fixed and - * a client DCB is created to handle the new connection. Further DCB details - * are set before returning the new DCB to the caller, or returning NULL if - * no new connection could be achieved. + * @brief Accept a new client connection * * @param listener Listener that has a new connection request * * @return DCB - The new client DCB for the new connection, or NULL if failed */ -DCB* dcb_accept(const SListener& listener) +DCB* accept_one_dcb(const SListener& listener) { DCB* client_dcb = NULL; int c_sock; struct sockaddr_storage client_conn; - if ((c_sock = dcb_accept_one_connection(listener->fd(), (struct sockaddr*)&client_conn)) >= 0) + if ((c_sock = accept_one_connection(listener->fd(), (struct sockaddr*)&client_conn)) >= 0) { configure_network_socket(c_sock, client_conn.ss_family); @@ -1079,7 +1015,7 @@ uint32_t Listener::poll_handler(MXB_POLL_DATA* data, MXB_WORKER* worker, uint32_ Listener* listener = static_cast(data); DCB* client_dcb; - while ((client_dcb = dcb_accept(listener->m_self))) + while ((client_dcb = accept_one_dcb(listener->m_self))) { listener->m_proto_func.accept(client_dcb); }