diff extensions/rt_default/rt_default.c @ 1336:cec0812038bb

rt_default: add reload support. When SIGUSR1 is sent to the freeDiameter process, rt_default reloads its config file. Written for Effortel Technologies SA, published with their consent.
author Thomas Klausner <tk@giga.or.at>
date Tue, 09 Apr 2019 15:46:50 +0200
parents f937feb72734
children 566bb46cc73f
line wrap: on
line diff
--- a/extensions/rt_default/rt_default.c	Tue Apr 09 15:43:23 2019 +0200
+++ b/extensions/rt_default/rt_default.c	Tue Apr 09 15:46:50 2019 +0200
@@ -37,38 +37,101 @@
  * Configurable routing of messages for freeDiameter.
  */
 
+#include <signal.h>
+
 #include "rt_default.h"
 
+#define MODULE_NAME "rt_default"
+
+#include <pthread.h>
+
+static pthread_rwlock_t rtd_lock;
+
+static char *rtd_config_file;
+
 /* The callback called on new messages */
 static int rtd_out(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
 {
 	struct msg * msg = *pmsg;
 	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
+	int ret;
 	
 	CHECK_PARAMS(msg && candidates);
-	
+
+	if (pthread_rwlock_rdlock(&rtd_lock) != 0) {
+		fd_log_notice("%s: read-lock failed, skipping handler", MODULE_NAME);
+		return 0;
+	}
 	/* Simply pass it to the appropriate function */
 	if (FD_IS_LIST_EMPTY(candidates)) {
-		return 0;
+		ret = 0;
 	} else {
-		return rtd_process( msg, candidates );
+		ret = rtd_process( msg, candidates );
 	}
+	if (pthread_rwlock_unlock(&rtd_lock) != 0) {
+		fd_log_notice("%s: read-unlock failed after rtd_out, exiting", MODULE_NAME);
+		exit(1);
+	}
+	return ret;
 }
 
 /* handler */
 static struct fd_rt_out_hdl * rtd_hdl = NULL;
 
+static volatile int in_signal_handler = 0;
+
+/* signal handler */
+static void sig_hdlr(void)
+{
+	if (in_signal_handler) {
+		fd_log_error("%s: already handling a signal, ignoring new one", MODULE_NAME);
+		return;
+	}
+	in_signal_handler = 1;
+
+	if (pthread_rwlock_wrlock(&rtd_lock) != 0) {
+		fd_log_error("%s: locking failed, aborting config reload", MODULE_NAME);
+		return;
+	}
+	rtd_conf_reload(rtd_config_file);
+	if (pthread_rwlock_unlock(&rtd_lock) != 0) {
+		fd_log_error("%s: unlocking failed after config reload, exiting", MODULE_NAME);
+		exit(1);
+	}		
+
+	fd_log_notice("%s: reloaded configuration", MODULE_NAME);
+
+	in_signal_handler = 0;
+}
+
+
 /* entry point */
 static int rtd_entry(char * conffile)
 {
 	TRACE_ENTRY("%p", conffile);
-	
+
+	rtd_config_file = conffile;
+	pthread_rwlock_init(&rtd_lock, NULL);
+
+	if (pthread_rwlock_wrlock(&rtd_lock) != 0) {
+		fd_log_notice("%s: write-lock failed, aborting", MODULE_NAME);
+		return EDEADLK;
+	}
+
 	/* Initialize the repo */
 	CHECK_FCT( rtd_init() );
 	
 	/* Parse the configuration file */
 	CHECK_FCT( rtd_conf_handle(conffile) );
-	
+
+	if (pthread_rwlock_unlock(&rtd_lock) != 0) {
+		fd_log_notice("%s: write-unlock failed, aborting", MODULE_NAME);
+		return EDEADLK;
+	}
+
+	/* Register reload callback */
+	CHECK_FCT(fd_event_trig_regcb(SIGUSR1, MODULE_NAME, sig_hdlr));
+
 #if 0
 	/* Dump the rules */
 	rtd_dump();
@@ -91,9 +154,11 @@
 	
 	/* Destroy the data */
 	rtd_fini();
-	
+
+	pthread_rwlock_destroy(&rtd_lock);
+
 	/* Done */
 	return ;
 }
 
-EXTENSION_ENTRY("rt_default", rtd_entry);
+EXTENSION_ENTRY(MODULE_NAME, rtd_entry);
"Welcome to our mercurial repository"