diff --git a/include/common/hathreads.h b/include/common/hathreads.h index f68dc7ee1..25c1737e1 100644 --- a/include/common/hathreads.h +++ b/include/common/hathreads.h @@ -170,6 +170,7 @@ enum lock_label { SPOE_APPLET_LOCK, DNS_LOCK, PID_LIST_LOCK, + EMAIL_ALERTS_LOCK, LOCK_LABELS }; struct lock_stat { @@ -258,7 +259,7 @@ static inline void show_lock_stats() "UPDATED_SERVERS", "LBPRM", "SIGNALS", "STK_TABLE", "STK_SESS", "APPLETS", "PEER", "BUF_WQ", "STREAMS", "SSL", "SSL_GEN_CERTS", "PATREF", "PATEXP", "PATLRU", "VARS", "COMP_POOL", "LUA", - "NOTIF", "SPOE_APPLET", "DNS", "PID_LIST" }; + "NOTIF", "SPOE_APPLET", "DNS", "PID_LIST", "EMAIL_ALERTS" }; int lbl; for (lbl = 0; lbl < LOCK_LABELS; lbl++) { diff --git a/include/types/proxy.h b/include/types/proxy.h index 3e0c3eeed..719c8dd99 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -239,6 +239,9 @@ struct email_alertq { * code even though they are not checks. This structure * is as a parameter to the check code. * Each check corresponds to a mailer */ +#ifdef USE_THREAD + HA_SPINLOCK_T lock; +#endif }; struct proxy { diff --git a/src/checks.c b/src/checks.c index 0944c0e3b..d07e508fc 100644 --- a/src/checks.c +++ b/src/checks.c @@ -851,7 +851,7 @@ static void event_srv_chk_r(struct connection *conn) check->code = str2uic(check->bi->data + 9); desc = ltrim(check->bi->data + 12, ' '); - + if ((s->proxy->options & PR_O_DISABLE404) && (s->next_state != SRV_ST_STOPPED) && (check->code == 404)) { /* 404 may be accepted as "stopping" only if the server was up */ @@ -3078,13 +3078,14 @@ static struct task *process_email_alert(struct task *t) q = container_of(check, typeof(*q), check); + SPIN_LOCK(EMAIL_ALERTS_LOCK, &q->lock); while (1) { if (!(check->state & CHK_ST_ENABLED)) { if (LIST_ISEMPTY(&q->email_alerts)) { /* All alerts processed, queue the task */ t->expire = TICK_ETERNITY; task_queue(t); - return t; + goto end; } alert = LIST_NEXT(&q->email_alerts, typeof(alert), list); @@ -3106,6 +3107,8 @@ static struct task *process_email_alert(struct task *t) check->server = NULL; check->state &= ~CHK_ST_ENABLED; } + end: + SPIN_UNLOCK(EMAIL_ALERTS_LOCK, &q->lock); return t; } @@ -3132,7 +3135,7 @@ int init_email_alert(struct mailers *mls, struct proxy *p, char **err) struct task *t; LIST_INIT(&q->email_alerts); - + SPIN_INIT(&q->lock); check->inter = mls->timeout.mail; check->rise = DEF_AGENT_RISETIME; check->fall = DEF_AGENT_FALLTIME; @@ -3336,8 +3339,10 @@ static int enqueue_one_email_alert(struct proxy *p, struct server *s, if (!add_tcpcheck_expect_str(&alert->tcpcheck_rules, "221 ")) goto error; + SPIN_LOCK(EMAIL_ALERTS_LOCK, &q->lock); task_wakeup(check->task, TASK_WOKEN_MSG); LIST_ADDQ(&q->email_alerts, &alert->list); + SPIN_UNLOCK(EMAIL_ALERTS_LOCK, &q->lock); return 1; error: