MEDIUM: unix: avoid a double connect probe when no data are sent

Plain "tcp" health checks sent to a unix socket cause two connect()
calls to be made, one to connect, and a second one to verify that the
connection properly established. But with unix sockets, we get
immediate notification of success, so we can avoid this second
attempt. However we need to ensure that we'll visit the connection
handler even if there's no remaining handshake pending, so for this
we claim we have some data to send in order to enable polling for
writes if there's no more handshake.
This commit is contained in:
Willy Tarreau 2014-05-10 09:48:28 +02:00
parent 3543cdbd17
commit 7bb21532f4
1 changed files with 22 additions and 6 deletions

View File

@ -381,7 +381,7 @@ int uxst_connect_server(struct connection *conn, int data, int delack)
struct server *srv;
struct proxy *be;
conn->flags = CO_FL_WAIT_L4_CONN; /* connection in progress */
conn->flags = 0;
switch (obj_type(conn->target)) {
case OBJ_TYPE_PROXY:
@ -457,9 +457,14 @@ int uxst_connect_server(struct connection *conn, int data, int delack)
if (global.tune.server_rcvbuf)
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &global.tune.server_rcvbuf, sizeof(global.tune.server_rcvbuf));
if ((connect(fd, (struct sockaddr *)&conn->addr.to, get_addr_len(&conn->addr.to)) == -1) &&
(errno != EINPROGRESS) && (errno != EALREADY) && (errno != EISCONN)) {
if (errno == EAGAIN || errno == EADDRINUSE || errno == EADDRNOTAVAIL) {
if (connect(fd, (struct sockaddr *)&conn->addr.to, get_addr_len(&conn->addr.to)) == -1) {
if (errno == EALREADY || errno == EISCONN) {
conn->flags &= ~CO_FL_WAIT_L4_CONN;
}
else if (errno == EINPROGRESS) {
conn->flags |= CO_FL_WAIT_L4_CONN;
}
else if (errno == EAGAIN || errno == EADDRINUSE || errno == EADDRNOTAVAIL) {
char *msg;
if (errno == EAGAIN || errno == EADDRNOTAVAIL) {
msg = "no free ports";
@ -489,6 +494,16 @@ int uxst_connect_server(struct connection *conn, int data, int delack)
return SN_ERR_SRVCL;
}
}
else {
/* connect() already succeeded, which is quite usual for unix
* sockets. Let's avoid a second connect() probe to complete it,
* but we need to ensure we'll wake up if there's no more handshake
* pending (eg: for health checks).
*/
conn->flags &= ~CO_FL_WAIT_L4_CONN;
if (!(conn->flags & CO_FL_HANDSHAKE))
data = 1;
}
conn->flags |= CO_FL_ADDR_TO_SET;
@ -497,8 +512,9 @@ int uxst_connect_server(struct connection *conn, int data, int delack)
conn->flags |= CO_FL_SEND_PROXY;
conn_ctrl_init(conn); /* registers the FD */
fdtab[fd].linger_risk = 1; /* close hard if needed */
conn_sock_want_send(conn); /* for connect status */
fdtab[fd].linger_risk = 0; /* no need to disable lingering */
if (conn->flags & CO_FL_HANDSHAKE)
conn_sock_want_send(conn); /* for connect status or proxy protocol */
if (conn_xprt_init(conn) < 0) {
conn_force_close(conn);