asterisk/res/res_limit.c
Leif Madsen a525edea59 Merged revisions 328247 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.10

................
  r328247 | lmadsen | 2011-07-14 16:25:31 -0400 (Thu, 14 Jul 2011) | 14 lines
  
  Merged revisions 328209 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/branches/1.8
  
  ........
    r328209 | lmadsen | 2011-07-14 16:13:06 -0400 (Thu, 14 Jul 2011) | 6 lines
    
    Introduce <support_level> tags in MODULEINFO.
    This change introduces MODULEINFO into many modules in Asterisk in order to show
    the community support level for those modules. This is used by changes committed
    to menuselect by Russell Bryant recently (r917 in menuselect). More information about
    the support level types and what they mean is available on the wiki at
    https://wiki.asterisk.org/wiki/display/AST/Asterisk+Module+Support+States
  ........
................


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@328259 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2011-07-14 20:28:54 +00:00

219 lines
5.4 KiB
C

/*
* Asterisk -- A telephony toolkit for Linux.
*
* Resource limits
*
* Copyright (c) 2006 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <res_limit_200607@the-tilghman.com>
*
* This code is released by the author with no restrictions on usage.
*
*/
/*! \file
*
* \brief Resource limits
*
* \author Tilghman Lesher <res_limit_200607@the-tilghman.com>
*/
/*** MODULEINFO
<support_level>core</support_level>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <ctype.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "asterisk/module.h"
#include "asterisk/cli.h"
/* Find proper rlimit for virtual memory */
#ifdef RLIMIT_AS
#define VMEM_DEF RLIMIT_AS
#else
#ifdef RLIMIT_VMEM
#define VMEM_DEF RLIMIT_VMEM
#endif
#endif
static const struct limits {
int resource;
char limit[3];
char desc[40];
char clicmd[15];
} limits[] = {
{ RLIMIT_CPU, "-t", "cpu time", "time" },
{ RLIMIT_FSIZE, "-f", "file size" , "file" },
{ RLIMIT_DATA, "-d", "program data segment", "data" },
{ RLIMIT_STACK, "-s", "program stack size", "stack" },
{ RLIMIT_CORE, "-c", "core file size", "core" },
#ifdef RLIMIT_RSS
{ RLIMIT_RSS, "-m", "resident memory", "memory" },
{ RLIMIT_MEMLOCK, "-l", "amount of memory locked into RAM", "locked" },
#endif
#ifdef RLIMIT_NPROC
{ RLIMIT_NPROC, "-u", "number of processes", "processes" },
#endif
{ RLIMIT_NOFILE, "-n", "number of file descriptors", "descriptors" },
#ifdef VMEM_DEF
{ VMEM_DEF, "-v", "virtual memory", "virtual" },
#endif
};
static int str2limit(const char *string)
{
size_t i;
for (i = 0; i < ARRAY_LEN(limits); i++) {
if (!strcasecmp(string, limits[i].clicmd))
return limits[i].resource;
}
return -1;
}
static const char *str2desc(const char *string)
{
size_t i;
for (i = 0; i < ARRAY_LEN(limits); i++) {
if (!strcmp(string, limits[i].clicmd))
return limits[i].desc;
}
return "<unknown>";
}
static char *complete_ulimit(struct ast_cli_args *a)
{
int which = 0, i;
int wordlen = strlen(a->word);
if (a->pos > 1)
return NULL;
for (i = 0; i < ARRAY_LEN(limits); i++) {
if (!strncasecmp(limits[i].clicmd, a->word, wordlen)) {
if (++which > a->n)
return ast_strdup(limits[i].clicmd);
}
}
return NULL;
}
static char *handle_cli_ulimit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
int resource;
struct rlimit rlimit = { 0, 0 };
switch (cmd) {
case CLI_INIT:
e->command = "ulimit";
e->usage =
"Usage: ulimit {data|"
#ifdef RLIMIT_RSS
"limit|"
#endif
"file|"
#ifdef RLIMIT_RSS
"memory|"
#endif
"stack|time|"
#ifdef RLIMIT_NPROC
"processes|"
#endif
#ifdef VMEM_DEF
"virtual|"
#endif
"core|descriptors} [<num>]\n"
" Shows or sets the corresponding resource limit.\n"
" data Process data segment [readonly]\n"
#ifdef RLIMIT_RSS
" lock Memory lock size [readonly]\n"
#endif
" file File size\n"
#ifdef RLIMIT_RSS
" memory Process resident memory [readonly]\n"
#endif
" stack Process stack size [readonly]\n"
" time CPU usage [readonly]\n"
#ifdef RLIMIT_NPROC
" processes Child processes\n"
#endif
#ifdef VMEM_DEF
" virtual Process virtual memory [readonly]\n"
#endif
" core Core dump file size\n"
" descriptors Number of file descriptors\n";
return NULL;
case CLI_GENERATE:
return complete_ulimit(a);
}
if (a->argc > 3)
return CLI_SHOWUSAGE;
if (a->argc == 1) {
char arg2[15];
const char * const newargv[2] = { "ulimit", arg2 };
for (resource = 0; resource < ARRAY_LEN(limits); resource++) {
struct ast_cli_args newArgs = { .argv = newargv, .argc = 2 };
ast_copy_string(arg2, limits[resource].clicmd, sizeof(arg2));
handle_cli_ulimit(e, CLI_HANDLER, &newArgs);
}
return CLI_SUCCESS;
} else {
resource = str2limit(a->argv[1]);
if (resource == -1) {
ast_cli(a->fd, "Unknown resource\n");
return CLI_FAILURE;
}
if (a->argc == 3) {
int x;
#ifdef RLIMIT_NPROC
if (resource != RLIMIT_NOFILE && resource != RLIMIT_CORE && resource != RLIMIT_NPROC && resource != RLIMIT_FSIZE) {
#else
if (resource != RLIMIT_NOFILE && resource != RLIMIT_CORE && resource != RLIMIT_FSIZE) {
#endif
ast_cli(a->fd, "Resource not permitted to be set\n");
return CLI_FAILURE;
}
sscanf(a->argv[2], "%30d", &x);
rlimit.rlim_max = rlimit.rlim_cur = x;
setrlimit(resource, &rlimit);
return CLI_SUCCESS;
} else {
if (!getrlimit(resource, &rlimit)) {
char printlimit[32];
const char *desc;
if (rlimit.rlim_max == RLIM_INFINITY)
ast_copy_string(printlimit, "effectively unlimited", sizeof(printlimit));
else
snprintf(printlimit, sizeof(printlimit), "limited to %d", (int) rlimit.rlim_cur);
desc = str2desc(a->argv[1]);
ast_cli(a->fd, "%c%s (%s) is %s.\n", toupper(desc[0]), desc + 1, a->argv[1], printlimit);
} else
ast_cli(a->fd, "Could not retrieve resource limits for %s: %s\n", str2desc(a->argv[1]), strerror(errno));
return CLI_SUCCESS;
}
}
}
static struct ast_cli_entry cli_ulimit =
AST_CLI_DEFINE(handle_cli_ulimit, "Set or show process resource limits");
static int unload_module(void)
{
return ast_cli_unregister(&cli_ulimit);
}
static int load_module(void)
{
return ast_cli_register(&cli_ulimit) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Resource limits");