diff --git a/daemon/cli.c b/daemon/cli.c index f6069f84f..de6233432 100644 --- a/daemon/cli.c +++ b/daemon/cli.c @@ -212,6 +212,45 @@ static void cli_incoming_list_callid(char* buffer, int len, struct callmaster* m obj_put(c); } +static void cli_incoming_set_max_open_files(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) { + int printlen = 0; + unsigned int open_files_num; + str open_files; + pid_t pid; + + // limit the minimum number of open files to avoid rtpengine freeze for low open_files_num values + unsigned int min_open_files_num = (1 << 16); + + if (len<=1) { + printlen = snprintf(replybuffer,(outbufend-replybuffer), "%s\n", "More parameters required."); + ADJUSTLEN(printlen,outbufend,replybuffer); + return; + } + + ++buffer; --len; // one space + open_files.s = buffer; + open_files.len = len; + open_files_num = str_to_ui(&open_files, -1); + + if (open_files_num == -1) { + printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting open_files to %.*s; not an unsigned integer\n", open_files.len, open_files.s); + ADJUSTLEN(printlen,outbufend,replybuffer); + return; + } else if (open_files_num < min_open_files_num) { + printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting open_files to %.*s; can't set it under %u\n", open_files.len, open_files.s, min_open_files_num); + ADJUSTLEN(printlen,outbufend,replybuffer); + return; + } else if (rlim(RLIMIT_NOFILE, open_files_num) == -1){ + printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting open_files to %.*s; errno = %d\n", open_files.len, open_files.s, errno); + ADJUSTLEN(printlen,outbufend,replybuffer); + return; + } else { + pid = getpid(); + printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting open_files to %.*s; cat /proc/%u/limits\n", open_files.len, open_files.s, pid); + 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; @@ -262,6 +301,26 @@ static void cli_incoming_list(char* buffer, int len, struct callmaster* m, char* } } +static void cli_incoming_set(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) { + int printlen=0; + + static const char* SET_OPEN_FILES = "max-open-files"; + + if (len<=1) { + printlen = snprintf(replybuffer, outbufend-replybuffer, "%s\n", "More parameters required."); + ADJUSTLEN(printlen,outbufend,replybuffer); + return; + } + ++buffer; --len; // one space + + if (len>=strlen(SET_OPEN_FILES) && strncmp(buffer,SET_OPEN_FILES,strlen(SET_OPEN_FILES)) == 0) { + cli_incoming_set_max_open_files(buffer+strlen(SET_OPEN_FILES), len-strlen(SET_OPEN_FILES), m, replybuffer, outbufend); + } else { + printlen = snprintf(replybuffer, outbufend-replybuffer, "%s:%s\n", "Unknown 'set' command", buffer); + ADJUSTLEN(printlen,outbufend,replybuffer); + } +} + static void cli_incoming_terminate(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) { str termparam; struct call* c=0; @@ -334,9 +393,9 @@ static void cli_incoming(int fd, void *p, uintptr_t u) { struct cli *cli = (void *) p; socklen_t sinl; static const int BUFLENGTH = 4096*1024; - char replybuffer[BUFLENGTH]; - char* outbuf = replybuffer; - const char* outbufend = replybuffer+BUFLENGTH; + char replybuffer[BUFLENGTH]; + char* outbuf = replybuffer; + const char* outbufend = replybuffer+BUFLENGTH; static const int MAXINPUT = 1024; char inbuf[MAXINPUT]; int inlen = 0, readbytes = 0; @@ -374,12 +433,14 @@ next: static const char* LIST = "list"; static const char* TERMINATE = "terminate"; + static const char* SET = "set"; if (strncmp(inbuf,LIST,strlen(LIST)) == 0) { cli_incoming_list(inbuf+strlen(LIST), inlen-strlen(LIST), cli->callmaster, outbuf, outbufend); - } else if (strncmp(inbuf,TERMINATE,strlen(TERMINATE)) == 0) { cli_incoming_terminate(inbuf+strlen(TERMINATE), inlen-strlen(TERMINATE), cli->callmaster, outbuf, outbufend); + } else if (strncmp(inbuf,SET,strlen(SET)) == 0) { + cli_incoming_set(inbuf+strlen(SET), inlen-strlen(SET), cli->callmaster, outbuf, outbufend); } else { sprintf(replybuffer, "%s:%s\n", "Unknown or incomplete command:", inbuf); } diff --git a/daemon/main.c b/daemon/main.c index 3b6241567..3b671e397 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -149,7 +149,7 @@ static void resources(void) { int tryv; rlim(RLIMIT_CORE, RLIM_INFINITY); - for (tryv = ((1<<16) - 1); tryv && rlim(RLIMIT_NOFILE, tryv) == -1; tryv >>= 1) + for (tryv = ((1<<20) - 1); tryv && rlim(RLIMIT_NOFILE, tryv) == -1; tryv >>= 1) ; rlim(RLIMIT_DATA, RLIM_INFINITY); diff --git a/daemon/str.h b/daemon/str.h index 084017a3b..dc42b4f85 100644 --- a/daemon/str.h +++ b/daemon/str.h @@ -63,6 +63,8 @@ INLINE int str_str(const str *s, const char *sub); INLINE void str_swap(str *a, str *b); /* parses a string into an int, returns default if conversion fails */ INLINE int str_to_i(str *s, int def); +/* parses a string uinto an int, returns default if conversion fails */ +INLINE uint str_to_ui(str *s, int def); /* asprintf() analogs */ #define str_sprintf(fmt, a...) __str_sprintf(STR_MALLOC_PADDING fmt, a) @@ -256,4 +258,18 @@ INLINE int str_to_i(str *s, int def) { return ret; } +INLINE unsigned int str_to_ui(str *s, int def) { + char c, *ep; + long ret; + if (s->len <= 0) + return def; + c = s->s[s->len]; + s->s[s->len] = '\0'; + ret = strtol(s->s, &ep, 10); + s->s[s->len] = c; + if (ep == s->s) + return def; + return ret; +} + #endif diff --git a/utils/rtpengine-ctl b/utils/rtpengine-ctl index d39c48f25..4179197ab 100755 --- a/utils/rtpengine-ctl +++ b/utils/rtpengine-ctl @@ -72,6 +72,9 @@ sub showusage { print " all : terminates all current sessions\n"; print " : session is immediately terminated\n"; print "\n"; + print " set [ max-open-files ]\n"; + print " max-open-files : increase the max nr of allowed open files\n"; + print "\n"; print "\n"; print " Return Value:\n"; print " 0 on success with ouput from server side, other values for failure.\n";