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

View File

@ -830,106 +830,42 @@ int start_listening(const char* config)
/** /**
* @brief Accept a new client connection, given listener, return file descriptor * @brief Accept a new client connection
*
* 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.
* *
* @param fd File descriptor to accept from * @param fd File descriptor to accept from
* @param client_conn Output where connection information is stored * @param client_conn Output where connection information is stored
* *
* @return -1 for failure, or a file descriptor for the new connection * @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 */ /* new connection from client */
for (int i = 0; i < 10; i++) 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); MXS_ERROR("Failed to accept new client connection: %d, %s", errno, mxs_strerror(errno));
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;
}
} }
return c_sock;
return client_fd;
} }
/** /**
* @brief Accept a new client connection, given a listener, return new DCB * @brief Accept a new client connection
*
* 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.
* *
* @param listener Listener that has a new connection request * @param listener Listener that has a new connection request
* *
* @return DCB - The new client DCB for the new connection, or NULL if failed * @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; DCB* client_dcb = NULL;
int c_sock; int c_sock;
struct sockaddr_storage client_conn; 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); 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); Listener* listener = static_cast<Listener*>(data);
DCB* client_dcb; 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); listener->m_proto_func.accept(client_dcb);
} }