*/
static inline void health_adjust(struct server *s, short status)
{
+ SPIN_LOCK(SERVER_LOCK, &s->lock);
/* return now if observing nor health check is not enabled */
- if (!s->observe || !s->check.task)
+ if (!s->observe || !s->check.task) {
+ SPIN_UNLOCK(SERVER_LOCK, &s->lock);
return;
+ }
- return __health_adjust(s, status);
+ __health_adjust(s, status);
+ SPIN_UNLOCK(SERVER_LOCK, &s->lock);
}
const char *init_check(struct check *check, int type);
}
}
+ SPIN_LOCK(SERVER_LOCK, &check->server->lock);
if (check->state & CHK_ST_PORT_MISS) {
/* NOTE: this is reported after <fall> tries */
chunk_printf(chk, "No port available for the TCP connection");
else /* HTTP, SMTP, ... */
set_server_check_status(check, HCHK_STATUS_L7TOUT, err_msg);
}
+ SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
return;
}
int done;
unsigned short msglen;
+ SPIN_LOCK(SERVER_LOCK, &check->server->lock);
+
if (unlikely(check->result == CHK_RES_FAILED))
goto out_wakeup;
- if (conn->flags & CO_FL_HANDSHAKE)
+ if (conn->flags & CO_FL_HANDSHAKE) {
+ SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
return;
+ }
/* wake() will take care of calling tcpcheck_main() */
- if (check->type == PR_O2_TCPCHK_CHK)
+ if (check->type == PR_O2_TCPCHK_CHK) {
+ SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
return;
+ }
/* Warning! Linux returns EAGAIN on SO_ERROR if data are still available
* but the connection was closed on the remote end. Fortunately, recv still
!isdigit((unsigned char) *(check->bi->data + 2))) {
cut_crlf(check->bi->data);
set_server_check_status(check, HCHK_STATUS_L7RSP, check->bi->data);
-
goto out_wakeup;
}
else {
if (!done)
goto wait_more_data;
+
/* it seems we have a OK packet but without a valid length,
* it must be a protocol error
*/
else {
if (!done)
goto wait_more_data;
+
/* it seems we have a Handshake Initialization packet but without a valid length,
* it must be a protocol error
*/
if ((msglen > 2) ||
(memcmp(check->bi->data + 2 + msglen, "\x02\x01\x01\x61", 4) != 0)) {
set_server_check_status(check, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
-
goto out_wakeup;
}
if ((msglen > 4) ||
(memcmp(check->bi->data + 7 + msglen, "\x0a\x01", 2) != 0)) {
set_server_check_status(check, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
-
goto out_wakeup;
}
break;
} /* switch */
+ SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
out_wakeup:
/* collect possible new errors */
if (conn->flags & CO_FL_ERROR)
struct server *srv;
srv = hlua_check_server(L, 1);
+ SPIN_LOCK(SERVER_LOCK, &srv->lock);
srv_shutdown_streams(srv, SF_ERR_KILLED);
+ SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
return 0;
}
struct server *srv;
srv = hlua_check_server(L, 1);
+ SPIN_LOCK(SERVER_LOCK, &srv->lock);
srv_adm_set_drain(srv);
+ SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
return 0;
}
struct server *srv;
srv = hlua_check_server(L, 1);
+ SPIN_LOCK(SERVER_LOCK, &srv->lock);
srv_adm_set_maint(srv);
+ SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
return 0;
}
struct server *srv;
srv = hlua_check_server(L, 1);
+ SPIN_LOCK(SERVER_LOCK, &srv->lock);
srv_adm_set_ready(srv);
+ SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
return 0;
}
struct server *sv;
sv = hlua_check_server(L, 1);
+ SPIN_LOCK(SERVER_LOCK, &sv->lock);
if (sv->check.state & CHK_ST_CONFIGURED) {
sv->check.state |= CHK_ST_ENABLED;
}
+ SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 0;
}
struct server *sv;
sv = hlua_check_server(L, 1);
+ SPIN_LOCK(SERVER_LOCK, &sv->lock);
if (sv->check.state & CHK_ST_CONFIGURED) {
sv->check.state &= ~CHK_ST_ENABLED;
}
+ SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 0;
}
sv = hlua_check_server(L, 1);
if (!(sv->track)) {
+ SPIN_LOCK(SERVER_LOCK, &sv->lock);
sv->check.health = sv->check.rise + sv->check.fall - 1;
srv_set_running(sv, "changed from Lua script", NULL);
+ SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
}
return 0;
}
sv = hlua_check_server(L, 1);
if (!(sv->track)) {
+ SPIN_LOCK(SERVER_LOCK, &sv->lock);
sv->check.health = sv->check.rise + sv->check.fall - 1;
srv_set_stopping(sv, "changed from Lua script", NULL);
+ SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
}
return 0;
}
struct server *sv;
sv = hlua_check_server(L, 1);
+ SPIN_LOCK(SERVER_LOCK, &sv->lock);
if (!(sv->track)) {
sv->check.health = 0;
srv_set_stopped(sv, "changed from Lua script", NULL);
}
+ SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 0;
}
struct server *sv;
sv = hlua_check_server(L, 1);
+ SPIN_LOCK(SERVER_LOCK, &sv->lock);
if (sv->agent.state & CHK_ST_CONFIGURED) {
sv->agent.state |= CHK_ST_ENABLED;
}
+ SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 0;
}
struct server *sv;
sv = hlua_check_server(L, 1);
+ SPIN_LOCK(SERVER_LOCK, &sv->lock);
if (sv->agent.state & CHK_ST_CONFIGURED) {
sv->agent.state &= ~CHK_ST_ENABLED;
}
+ SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 0;
}
struct server *sv;
sv = hlua_check_server(L, 1);
+ SPIN_LOCK(SERVER_LOCK, &sv->lock);
if (sv->agent.state & CHK_ST_ENABLED) {
sv->agent.health = sv->agent.rise + sv->agent.fall - 1;
srv_set_running(sv, "changed from Lua script", NULL);
}
+ SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 0;
}
struct server *sv;
sv = hlua_check_server(L, 1);
+ SPIN_LOCK(SERVER_LOCK, &sv->lock);
if (sv->agent.state & CHK_ST_ENABLED) {
sv->agent.health = 0;
srv_set_stopped(sv, "changed from Lua script", NULL);
}
+ SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 0;
}
}
srv_register_update(s);
- for (srv = s->trackers; srv; srv = srv->tracknext)
+ for (srv = s->trackers; srv; srv = srv->tracknext) {
+ SPIN_LOCK(SERVER_LOCK, &srv->lock);
srv_set_stopped(srv, NULL, NULL);
+ SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
+ }
}
/* Marks server <s> up regardless of its checks' statuses and provided it isn't
s->next_state = SRV_ST_RUNNING;
srv_register_update(s);
- for (srv = s->trackers; srv; srv = srv->tracknext)
+ for (srv = s->trackers; srv; srv = srv->tracknext) {
+ SPIN_LOCK(SERVER_LOCK, &srv->lock);
srv_set_running(srv, NULL, NULL);
+ SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
+ }
}
/* Marks server <s> stopping regardless of its checks' statuses and provided it
}
srv_register_update(s);
- for (srv = s->trackers; srv; srv = srv->tracknext)
+ for (srv = s->trackers; srv; srv = srv->tracknext) {
+ SPIN_LOCK(SERVER_LOCK, &srv->lock);
srv_set_stopping(srv, NULL, NULL);
+ SPIN_LOCK(SERVER_LOCK, &srv->lock);
+ }
}
/* Enables admin flag <mode> (among SRV_ADMF_*) on server <s>. This is used to
else if (mode & SRV_ADMF_DRAIN)
mode = SRV_ADMF_IDRAIN;
- for (srv = s->trackers; srv; srv = srv->tracknext)
+ for (srv = s->trackers; srv; srv = srv->tracknext) {
+ SPIN_LOCK(SERVER_LOCK, &srv->lock);
srv_set_admin_flag(srv, mode, cause);
+ SPIN_LOCK(SERVER_LOCK, &srv->lock);
+ }
}
/* Disables admin flag <mode> (among SRV_ADMF_*) on server <s>. This is used to
else if (mode & SRV_ADMF_DRAIN)
mode = SRV_ADMF_IDRAIN;
- for (srv = s->trackers; srv; srv = srv->tracknext)
+ for (srv = s->trackers; srv; srv = srv->tracknext) {
+ SPIN_LOCK(SERVER_LOCK, &srv->lock);
srv_clr_admin_flag(srv, mode);
+ SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
+ }
}
/* principle: propagate maint and drain to tracking servers. This is useful
return;
for (srv2 = srv->trackers; srv2; srv2 = srv2->tracknext) {
+ SPIN_LOCK(SERVER_LOCK, &srv2->lock);
if (srv->next_admin & (SRV_ADMF_MAINT | SRV_ADMF_CMAINT))
srv_set_admin_flag(srv2, SRV_ADMF_IMAINT, NULL);
if (srv->next_admin & SRV_ADMF_DRAIN)
srv_set_admin_flag(srv2, SRV_ADMF_IDRAIN, NULL);
+ SPIN_UNLOCK(SERVER_LOCK, &srv2->lock);
}
}
if (msg->len)
goto out;
+ SPIN_LOCK(SERVER_LOCK, &srv->lock);
/* recover operational state and apply it to this server
* and all servers tracking this one */
switch (srv_op_state) {
if (port_str)
srv->svc_port = port;
+ SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
break;
default:
if (!sv)
return 1;
+ SPIN_LOCK(SERVER_LOCK, &sv->lock);
+
if (strcmp(args[3], "weight") == 0) {
warning = server_parse_weight_change_request(sv, args[4]);
if (warning) {
appctx->ctx.cli.severity = LOG_ERR;
appctx->ctx.cli.msg = "can't unset 'port' since MAPPORTS is in use.\n";
appctx->st0 = CLI_ST_PRINT;
+ SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 1;
}
sv->check.port = i;
appctx->ctx.cli.severity = LOG_ERR;
appctx->ctx.cli.msg = "set server <b>/<s> addr requires an address and optionally a port.\n";
appctx->st0 = CLI_ST_PRINT;
+ SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 1;
}
else {
appctx->ctx.cli.msg = "'set server <srv>' only supports 'agent', 'health', 'state', 'weight', 'addr', 'fqdn' and 'check-port'.\n";
appctx->st0 = CLI_ST_PRINT;
}
+ SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 1;
}
reprocess = 1;
}
else if ((sv = findserver(px, value)) != NULL) {
+ SPIN_LOCK(SERVER_LOCK, &sv->lock);
switch (action) {
case ST_ADM_ACTION_DISABLE:
if (!(sv->cur_admin & SRV_ADMF_FMAINT)) {
if (px->state != PR_STSTOPPED) {
struct stream *sess, *sess_bck;
- SPIN_LOCK(SERVER_LOCK, &sv->lock);
list_for_each_entry_safe(sess, sess_bck, &sv->actconns, by_srv)
if (sess->srv_conn == sv)
stream_shutdown(sess, SF_ERR_KILLED);
- SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
altered_servers++;
total_servers++;
}
break;
}
+ SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
} else {
/* the server name is unknown or ambiguous (duplicate names) */
total_servers++;