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:
parent
3543cdbd17
commit
7bb21532f4
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue