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.
This commit is contained in:
Markus Mäkelä 2018-12-01 21:31:32 +02:00
parent 8046a314e5
commit cca3d15b90
No known key found for this signature in database
GPG Key ID: 72D48FCE664F7B19

View File

@ -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<Listener*>(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);
}