From bac271b39825817346f0975558b585de1974627a Mon Sep 17 00:00:00 2001 From: smititelu Date: Thu, 17 Mar 2016 16:13:57 +0100 Subject: [PATCH] Add callmaster config lock --- daemon/call.c | 2 + daemon/call.h | 4 ++ daemon/call_interfaces.c | 7 ++++ daemon/cli.c | 88 +++++++--------------------------------- daemon/main.c | 1 + 5 files changed, 29 insertions(+), 73 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index c4e7c4f58..b76126ee3 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -193,6 +193,7 @@ static void call_timer_iterator(void *key, void *val, void *ptr) { log_info_call(c); cm = c->callmaster; + rwlock_lock_r(&cm->conf.config_lock); if (cm->conf.final_timeout && poller_now >= (c->created + cm->conf.final_timeout)) { ilog(LOG_INFO, "Closing call due to final timeout"); @@ -281,6 +282,7 @@ delete: goto out; out: + rwlock_unlock_r(&cm->conf.config_lock); rwlock_unlock_r(&c->master_lock); log_info_clear(); } diff --git a/daemon/call.h b/daemon/call.h index e11106d7c..7e1f29d9a 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -421,10 +421,14 @@ struct call { struct callmaster_config { int kernelfd; int kernelid; + + /* everything below protected by config_lock */ + rwlock_t config_lock; int max_sessions; unsigned int timeout; unsigned int silent_timeout; unsigned int final_timeout; + unsigned int delete_delay; struct redis *redis; struct redis *redis_write; diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index c7b4fd5ec..0a1b82cd1 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -388,10 +388,12 @@ str *call_query_udp(char **out, struct callmaster *m) { rwlock_unlock_w(&c->master_lock); + rwlock_lock_r(&m->conf.config_lock); ret = str_sprintf("%s %lld "UINT64F" "UINT64F" "UINT64F" "UINT64F"\n", out[RE_UDP_COOKIE], (long long int) m->conf.silent_timeout - (poller_now - stats.last_packet), atomic64_get_na(&stats.totals[0].packets), atomic64_get_na(&stats.totals[1].packets), atomic64_get_na(&stats.totals[2].packets), atomic64_get_na(&stats.totals[3].packets)); + rwlock_unlock_r(&m->conf.config_lock); goto out; err: @@ -741,6 +743,7 @@ out: const char *call_offer_ng(bencode_item_t *input, struct callmaster *m, bencode_item_t *output, const char* addr, const endpoint_t *sin) { + rwlock_lock_r(&m->conf.config_lock); if (m->conf.max_sessions>=0) { rwlock_lock_r(&m->hashlock); if (g_hash_table_size(m->callhash) >= m->conf.max_sessions) { @@ -748,10 +751,14 @@ const char *call_offer_ng(bencode_item_t *input, struct callmaster *m, bencode_i atomic64_inc(&m->totalstats.total_rejected_sess); atomic64_inc(&m->totalstats_interval.total_rejected_sess); ilog(LOG_ERROR, "Parallel session limit reached (%i)",m->conf.max_sessions); + + rwlock_unlock_r(&m->conf.config_lock); return "Parallel session limit reached"; } rwlock_unlock_r(&m->hashlock); } + + rwlock_unlock_r(&m->conf.config_lock); return call_offer_answer_ng(input, m, output, OP_OFFER, addr, sin); } diff --git a/daemon/cli.c b/daemon/cli.c index 3bc6749b4..4d46c2540 100644 --- a/daemon/cli.c +++ b/daemon/cli.c @@ -141,6 +141,8 @@ static void cli_incoming_list_maxopenfiles(char* buffer, int len, struct callmas static void cli_incoming_list_timeout(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) { int printlen=0; + rwlock_lock_r(&m->conf.config_lock); + /* don't lock anything while reading the value */ printlen = snprintf(replybuffer,(outbufend-replybuffer), "TIMEOUT=%u\n", m->conf.timeout); ADJUSTLEN(printlen,outbufend,replybuffer); @@ -149,6 +151,8 @@ static void cli_incoming_list_timeout(char* buffer, int len, struct callmaster* printlen = snprintf(replybuffer,(outbufend-replybuffer), "FINAL_TIMEOUT=%u\n", m->conf.final_timeout); ADJUSTLEN(printlen,outbufend,replybuffer); + rwlock_unlock_r(&m->conf.config_lock); + return ; } @@ -334,13 +338,15 @@ static void cli_incoming_set_maxsessions(char* buffer, int len, struct callmaste printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting maxsessions to %d; either positive or -1 values allowed\n", maxsessions_num); ADJUSTLEN(printlen,outbufend,replybuffer); } else if (maxsessions_num == disabled) { - /* don't lock anything while writing the value - only this command modifies its value */ + rwlock_lock_w(&m->conf.config_lock); m->conf.max_sessions = maxsessions_num; + rwlock_unlock_w(&m->conf.config_lock); printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting maxsessions to %d; disable feature\n", maxsessions_num); ADJUSTLEN(printlen,outbufend,replybuffer); } else { - /* don't lock anything while writing the value - only this command modifies its value */ + rwlock_lock_w(&m->conf.config_lock); m->conf.max_sessions = maxsessions_num; + rwlock_unlock_w(&m->conf.config_lock); printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting maxsessions to %d\n", maxsessions_num); ADJUSTLEN(printlen,outbufend,replybuffer); } @@ -348,7 +354,7 @@ static void cli_incoming_set_maxsessions(char* buffer, int len, struct callmaste return; } -static void cli_incoming_set_timeout(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) { +static void cli_incoming_set_timeout(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend, unsigned int *conf_timeout) { int printlen = 0; unsigned int timeout_num; str timeout; @@ -375,78 +381,14 @@ static void cli_incoming_set_timeout(char* buffer, int len, struct callmaster* m return; } else { /* don't lock anything while writing the value - only this command modifies its value */ - m->conf.timeout = timeout_num; + rwlock_lock_w(&m->conf.config_lock); + *conf_timeout = timeout_num; + rwlock_unlock_w(&m->conf.config_lock); printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting timeout to %u\n", timeout_num); ADJUSTLEN(printlen,outbufend,replybuffer); } } -static void cli_incoming_set_silent_timeout(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) { - int printlen = 0; - unsigned int silent_timeout_num; - str silent_timeout; - char *endptr; - - if (len <= 1) { - printlen = snprintf(replybuffer,(outbufend-replybuffer), "%s\n", "More parameters required."); - ADJUSTLEN(printlen,outbufend,replybuffer); - return; - } - - ++buffer; --len; // one space - silent_timeout.s = buffer; - silent_timeout.len = len; - silent_timeout_num = strtol(silent_timeout.s, &endptr, 10); - - if ((errno == ERANGE && (silent_timeout_num == LONG_MAX || silent_timeout_num == LONG_MIN)) || (errno != 0 && silent_timeout_num == 0)) { - printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting silent_timeout to %.*s; errno=%d\n", silent_timeout.len, silent_timeout.s, errno); - ADJUSTLEN(printlen,outbufend,replybuffer); - return; - } else if (endptr == silent_timeout.s) { - printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting silent_timeout to %.*s; no digists found\n", silent_timeout.len, silent_timeout.s); - ADJUSTLEN(printlen,outbufend,replybuffer); - return; - } else { - /* don't lock anything while writing the value - only this command modifies its value */ - m->conf.silent_timeout = silent_timeout_num; - printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting silent_timeout to %u\n", silent_timeout_num); - ADJUSTLEN(printlen,outbufend,replybuffer); - } -} - -static void cli_incoming_set_final_timeout(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) { - int printlen = 0; - unsigned int final_timeout_num; - str final_timeout; - char *endptr; - - if (len <= 1) { - printlen = snprintf(replybuffer,(outbufend-replybuffer), "%s\n", "More parameters required."); - ADJUSTLEN(printlen,outbufend,replybuffer); - return; - } - - ++buffer; --len; // one space - final_timeout.s = buffer; - final_timeout.len = len; - final_timeout_num = strtol(final_timeout.s, &endptr, 10); - - if ((errno == ERANGE && (final_timeout_num == LONG_MAX || final_timeout_num == LONG_MIN)) || (errno != 0 && final_timeout_num == 0)) { - printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting final_timeout to %.*s; errno=%d\n", final_timeout.len, final_timeout.s, errno); - ADJUSTLEN(printlen,outbufend,replybuffer); - return; - } else if (endptr == final_timeout.s) { - printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting final_timeout to %.*s; no digists found\n", final_timeout.len, final_timeout.s); - ADJUSTLEN(printlen,outbufend,replybuffer); - return; - } else { - /* don't lock anything while writing the value - only this command modifies its value */ - m->conf.final_timeout = final_timeout_num; - printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting final_timeout to %u\n", final_timeout_num); - ADJUSTLEN(printlen,outbufend,replybuffer); - } -} - static void cli_incoming_list(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) { GHashTableIter iter; gpointer key, value; @@ -527,11 +469,11 @@ static void cli_incoming_set(char* buffer, int len, struct callmaster* m, char* } else if (len>=strlen(SET_MAX_SESSIONS) && strncmp(buffer,SET_MAX_SESSIONS,strlen(SET_MAX_SESSIONS)) == 0) { cli_incoming_set_maxsessions(buffer+strlen(SET_MAX_SESSIONS), len-strlen(SET_MAX_SESSIONS), m, replybuffer, outbufend); } else if (len>=strlen(SET_TIMEOUT) && strncmp(buffer,SET_TIMEOUT,strlen(SET_TIMEOUT)) == 0) { - cli_incoming_set_timeout(buffer+strlen(SET_TIMEOUT), len-strlen(SET_TIMEOUT), m, replybuffer, outbufend); + cli_incoming_set_timeout(buffer+strlen(SET_TIMEOUT), len-strlen(SET_TIMEOUT), m, replybuffer, outbufend, &m->conf.timeout); } else if (len>=strlen(SET_SILENT_TIMEOUT) && strncmp(buffer,SET_SILENT_TIMEOUT,strlen(SET_SILENT_TIMEOUT)) == 0) { - cli_incoming_set_silent_timeout(buffer+strlen(SET_SILENT_TIMEOUT), len-strlen(SET_SILENT_TIMEOUT), m, replybuffer, outbufend); + cli_incoming_set_timeout(buffer+strlen(SET_SILENT_TIMEOUT), len-strlen(SET_SILENT_TIMEOUT), m, replybuffer, outbufend, &m->conf.silent_timeout); } else if (len>=strlen(SET_FINAL_TIMEOUT) && strncmp(buffer,SET_FINAL_TIMEOUT,strlen(SET_FINAL_TIMEOUT)) == 0) { - cli_incoming_set_final_timeout(buffer+strlen(SET_FINAL_TIMEOUT), len-strlen(SET_FINAL_TIMEOUT), m, replybuffer, outbufend); + cli_incoming_set_timeout(buffer+strlen(SET_FINAL_TIMEOUT), len-strlen(SET_FINAL_TIMEOUT), m, replybuffer, outbufend, &m->conf.final_timeout); } else { printlen = snprintf(replybuffer, outbufend-replybuffer, "%s:%s\n", "Unknown 'set' command", buffer); ADJUSTLEN(printlen,outbufend,replybuffer); diff --git a/daemon/main.c b/daemon/main.c index 267133fba..4b1b56f50 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -534,6 +534,7 @@ no_kernel: dtls_timer(ctx->p); ZERO(mc); + rwlock_init(&mc.config_lock); mc.kernelfd = kfd; mc.kernelid = table; if (max_sessions < -1) {