mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-02-03 16:31:08 +01:00
MEDIUM: threads/signal: Add a lock to make signals thread-safe
A global lock has been added to protect the signal processing. So when a signal it triggered, only one thread will catch it.
This commit is contained in:
parent
c60def8368
commit
b79a94c9f3
@ -145,6 +145,7 @@ enum lock_label {
|
||||
TASK_RQ_LOCK,
|
||||
TASK_WQ_LOCK,
|
||||
POOL_LOCK,
|
||||
SIGNALS_LOCK,
|
||||
LOCK_LABELS
|
||||
};
|
||||
struct lock_stat {
|
||||
@ -228,7 +229,8 @@ struct ha_rwlock {
|
||||
static inline void show_lock_stats()
|
||||
{
|
||||
const char *labels[LOCK_LABELS] = {"THREAD_SYNC", "FDTAB", "FDCACHE", "FD", "POLL",
|
||||
"TASK_RQ", "TASK_WQ", "POOL" };
|
||||
"TASK_RQ", "TASK_WQ", "POOL",
|
||||
"SIGNALS" };
|
||||
int lbl;
|
||||
|
||||
for (lbl = 0; lbl < LOCK_LABELS; lbl++) {
|
||||
|
||||
@ -13,6 +13,8 @@
|
||||
|
||||
#include <signal.h>
|
||||
#include <common/standard.h>
|
||||
#include <common/hathreads.h>
|
||||
|
||||
#include <types/signal.h>
|
||||
#include <types/task.h>
|
||||
|
||||
@ -20,6 +22,10 @@ extern int signal_queue_len;
|
||||
extern struct signal_descriptor signal_state[];
|
||||
extern struct pool_head *pool2_sig_handlers;
|
||||
|
||||
#ifdef USE_THREAD
|
||||
extern HA_SPINLOCK_T signals_lock;
|
||||
#endif
|
||||
|
||||
void signal_handler(int sig);
|
||||
void __signal_process_queue();
|
||||
int signal_init();
|
||||
|
||||
@ -2819,6 +2819,10 @@ int main(int argc, char **argv)
|
||||
free(tids);
|
||||
free(threads);
|
||||
|
||||
#if defined(DEBUG_THREAD) || defined(DEBUG_FULL)
|
||||
show_lock_stats();
|
||||
#endif
|
||||
|
||||
#endif /* USE_THREAD */
|
||||
}
|
||||
else {
|
||||
|
||||
11
src/signal.c
11
src/signal.c
@ -31,6 +31,10 @@ struct pool_head *pool2_sig_handlers = NULL;
|
||||
sigset_t blocked_sig;
|
||||
int signal_pending = 0; /* non-zero if t least one signal remains unprocessed */
|
||||
|
||||
#ifdef USE_THREAD
|
||||
HA_SPINLOCK_T signals_lock;
|
||||
#endif
|
||||
|
||||
/* Common signal handler, used by all signals. Received signals are queued.
|
||||
* Signal number zero has a specific status, as it cannot be delivered by the
|
||||
* system, any function may call it to perform asynchronous signal delivery.
|
||||
@ -69,6 +73,9 @@ void __signal_process_queue()
|
||||
struct signal_descriptor *desc;
|
||||
sigset_t old_sig;
|
||||
|
||||
if (SPIN_TRYLOCK(SIGNALS_LOCK, &signals_lock))
|
||||
return;
|
||||
|
||||
/* block signal delivery during processing */
|
||||
sigprocmask(SIG_SETMASK, &blocked_sig, &old_sig);
|
||||
|
||||
@ -95,6 +102,7 @@ void __signal_process_queue()
|
||||
|
||||
/* restore signal delivery */
|
||||
sigprocmask(SIG_SETMASK, &old_sig, NULL);
|
||||
SPIN_UNLOCK(SIGNALS_LOCK, &signals_lock);
|
||||
}
|
||||
|
||||
/* perform minimal intializations, report 0 in case of error, 1 if OK. */
|
||||
@ -106,6 +114,8 @@ int signal_init()
|
||||
memset(signal_queue, 0, sizeof(signal_queue));
|
||||
memset(signal_state, 0, sizeof(signal_state));
|
||||
|
||||
SPIN_INIT(&signals_lock);
|
||||
|
||||
/* Ensure signals are not blocked. Some shells or service managers may
|
||||
* accidently block all of our signals unfortunately, causing lots of
|
||||
* zombie processes to remain in the background during reloads.
|
||||
@ -140,6 +150,7 @@ void deinit_signals()
|
||||
pool_free2(pool2_sig_handlers, sh);
|
||||
}
|
||||
}
|
||||
SPIN_DESTROY(&signals_lock);
|
||||
}
|
||||
|
||||
/* Register a function and an integer argument on a signal. A pointer to the
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user