#include "zlog.h"
#include "libfrr.h"
#include "libfrr_trace.h"
+#include "sigevent.h"
DEFINE_MTYPE_STATIC(LIB, FRR_PTHREAD, "FRR POSIX Thread");
DEFINE_MTYPE_STATIC(LIB, PTHREAD_PRIM, "POSIX sync primitives");
assert(frr_is_after_fork || !"trying to start thread before fork()");
- /* Ensure we never handle signals on a background thread by blocking
- * everything here (new thread inherits signal mask)
- */
- sigfillset(&blocksigs);
+ sigemptyset(&blocksigs);
+ frr_sigset_add_mainonly(&blocksigs);
+ /* new thread inherits mask */
pthread_sigmask(SIG_BLOCK, &blocksigs, &oldsigs);
frrtrace(1, frr_libfrr, frr_pthread_run, fpt->name);
#include "frrcu.h"
#include "seqlock.h"
#include "atomlist.h"
+#include "sigevent.h"
DEFINE_MTYPE_STATIC(LIB, RCU_THREAD, "RCU thread");
DEFINE_MTYPE_STATIC(LIB, RCU_NEXT, "RCU sequence barrier");
*/
sigset_t oldsigs, blocksigs;
- sigfillset(&blocksigs);
+ /* technically, the RCU thread is very poorly suited to run even just a
+ * crashlog handler, since zlog_sigsafe() could deadlock on transiently
+ * invalid (due to RCU) logging data structures
+ *
+ * but given that when we try to write a crashlog, we're already in
+ * b0rked territory anyway - give the crashlog handler a chance.
+ *
+ * (also cf. the SIGALRM usage in writing crashlogs to avoid hung
+ * processes on any kind of deadlock in crash handlers)
+ */
+ sigemptyset(&blocksigs);
+ frr_sigset_add_mainonly(&blocksigs);
+ /* new thread inherits mask */
pthread_sigmask(SIG_BLOCK, &blocksigs, &oldsigs);
rcu_active = true;
/* check whether there are signals to handle, process any found */
extern int frr_sigevent_process(void);
+/* Ensure we don't handle "application-type" signals on a secondary thread by
+ * blocking these signals when creating threads
+ *
+ * NB: SIGSEGV, SIGABRT, etc. must be allowed on all threads or we get no
+ * crashlogs. Since signals vary a little bit between platforms, below is a
+ * list of known things to go to the main thread. Any unknown signals should
+ * stay thread-local.
+ */
+static inline void frr_sigset_add_mainonly(sigset_t *blocksigs)
+{
+ /* signals we actively handle */
+ sigaddset(blocksigs, SIGHUP);
+ sigaddset(blocksigs, SIGINT);
+ sigaddset(blocksigs, SIGTERM);
+ sigaddset(blocksigs, SIGUSR1);
+
+ /* signals we don't actively use but that semantically belong */
+ sigaddset(blocksigs, SIGUSR2);
+ sigaddset(blocksigs, SIGQUIT);
+ sigaddset(blocksigs, SIGCHLD);
+ sigaddset(blocksigs, SIGPIPE);
+ sigaddset(blocksigs, SIGTSTP);
+ sigaddset(blocksigs, SIGTTIN);
+ sigaddset(blocksigs, SIGTTOU);
+ sigaddset(blocksigs, SIGWINCH);
+}
+
#ifdef __cplusplus
}
#endif