Wed Aug 18 22:33:55 2010

Asterisk developer's documentation


res_limit.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- A telephony toolkit for Linux.
00003  *
00004  * Resource limits
00005  * 
00006  * Copyright (c) 2006 Tilghman Lesher.  All rights reserved.
00007  *
00008  * Tilghman Lesher <res_limit_200607@the-tilghman.com>
00009  *
00010  * This code is released by the author with no restrictions on usage.
00011  *
00012  */
00013 
00014 /*! \file
00015  *
00016  * \brief Resource limits
00017  *
00018  * \author Tilghman Lesher <res_limit_200607@the-tilghman.com>
00019  */
00020 
00021 
00022 #include "asterisk.h"
00023 
00024 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 217035 $")
00025 
00026 #include <ctype.h>
00027 #include <sys/time.h>
00028 #include <sys/resource.h>
00029 #include "asterisk/module.h"
00030 #include "asterisk/cli.h"
00031 
00032 /* Find proper rlimit for virtual memory */
00033 #ifdef RLIMIT_AS
00034 #define VMEM_DEF RLIMIT_AS
00035 #else
00036 #ifdef RLIMIT_VMEM
00037 #define VMEM_DEF RLIMIT_VMEM
00038 #endif
00039 #endif
00040 
00041 static struct limits {
00042    int resource;
00043    char limit[3];
00044    char desc[40];
00045 } limits[] = {
00046    { RLIMIT_CPU,     "-t", "cpu time" },
00047    { RLIMIT_FSIZE,   "-f", "file size" },
00048    { RLIMIT_DATA,    "-d", "program data segment" },
00049    { RLIMIT_STACK,   "-s", "program stack size" },
00050    { RLIMIT_CORE,    "-c", "core file size" },
00051 #ifdef RLIMIT_RSS
00052    { RLIMIT_RSS,     "-m", "resident memory" },
00053    { RLIMIT_MEMLOCK, "-l", "amount of memory locked into RAM" },
00054 #endif
00055 #ifdef RLIMIT_NPROC
00056    { RLIMIT_NPROC,   "-u", "number of processes" },
00057 #endif
00058    { RLIMIT_NOFILE,  "-n", "number of file descriptors" },
00059 #ifdef VMEM_DEF
00060    { VMEM_DEF,       "-v", "virtual memory" },
00061 #endif
00062 };
00063 
00064 static int str2limit(const char *string)
00065 {
00066    size_t i;
00067    for (i = 0; i < ARRAY_LEN(limits); i++) {
00068       if (!strcasecmp(string, limits[i].limit))
00069          return limits[i].resource;
00070    }
00071    return -1;
00072 }
00073 
00074 static const char *str2desc(const char *string)
00075 {
00076    size_t i;
00077    for (i = 0; i < ARRAY_LEN(limits); i++) {
00078       if (!strcmp(string, limits[i].limit))
00079          return limits[i].desc;
00080    }
00081    return "<unknown>";
00082 }
00083 
00084 static char *complete_ulimit(struct ast_cli_args *a)
00085 {
00086    int which = 0, i;
00087    int wordlen = strlen(a->word);
00088 
00089    if (a->pos > 1)
00090       return NULL;
00091    for (i = 0; i < ARRAY_LEN(limits); i++) {
00092       if (!strncasecmp(limits[i].limit, a->word, wordlen)) {
00093          if (++which > a->n)
00094             return ast_strdup(limits[i].limit);
00095       }
00096    }
00097    return NULL;
00098 }
00099 
00100 static char *handle_cli_ulimit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00101 {
00102    int resource;
00103    struct rlimit rlimit = { 0, 0 };
00104 
00105    switch (cmd) {
00106    case CLI_INIT:
00107       e->command = "ulimit";
00108       e->usage =
00109          "Usage: ulimit {-d|"
00110 #ifdef RLIMIT_RSS
00111          "-l|"
00112 #endif
00113          "-f|"
00114 #ifdef RLIMIT_RSS
00115          "-m|"
00116 #endif
00117          "-s|-t|"
00118 #ifdef RLIMIT_NPROC
00119          "-u|"
00120 #endif
00121 #ifdef VMEM_DEF
00122          "-v|"
00123 #endif
00124          "-c|-n} [<num>]\n"
00125          "       Shows or sets the corresponding resource limit.\n"
00126          "         -d  Process data segment [readonly]\n"
00127 #ifdef RLIMIT_RSS
00128          "         -l  Memory lock size [readonly]\n"
00129 #endif
00130          "         -f  File size\n"
00131 #ifdef RLIMIT_RSS
00132          "         -m  Process resident memory [readonly]\n"
00133 #endif
00134          "         -s  Process stack size [readonly]\n"
00135          "         -t  CPU usage [readonly]\n"
00136 #ifdef RLIMIT_NPROC
00137          "         -u  Child processes\n"
00138 #endif
00139 #ifdef VMEM_DEF
00140          "         -v  Process virtual memory [readonly]\n"
00141 #endif
00142          "         -c  Core dump file size\n"
00143          "         -n  Number of file descriptors\n";
00144       return NULL;
00145    case CLI_GENERATE:
00146       return complete_ulimit(a);
00147    }
00148 
00149    if (a->argc > 3)
00150       return CLI_SHOWUSAGE;
00151 
00152    if (a->argc == 1) {
00153       char arg2[3];
00154       char *newargv[2] = { "ulimit", arg2 };
00155       for (resource = 0; resource < ARRAY_LEN(limits); resource++) {
00156          struct ast_cli_args newArgs = { .argv = newargv, .argc = 2 };
00157          ast_copy_string(arg2, limits[resource].limit, sizeof(arg2));
00158          handle_cli_ulimit(e, CLI_HANDLER, &newArgs);
00159       }
00160       return CLI_SUCCESS;
00161    } else {
00162       resource = str2limit(a->argv[1]);
00163       if (resource == -1) {
00164          ast_cli(a->fd, "Unknown resource\n");
00165          return CLI_FAILURE;
00166       }
00167 
00168       if (a->argc == 3) {
00169          int x;
00170 #ifdef RLIMIT_NPROC
00171          if (resource != RLIMIT_NOFILE && resource != RLIMIT_CORE && resource != RLIMIT_NPROC && resource != RLIMIT_FSIZE) {
00172 #else
00173          if (resource != RLIMIT_NOFILE && resource != RLIMIT_CORE && resource != RLIMIT_FSIZE) {
00174 #endif
00175             ast_cli(a->fd, "Resource not permitted to be set\n");
00176             return CLI_FAILURE;
00177          }
00178 
00179          sscanf(a->argv[2], "%30d", &x);
00180          rlimit.rlim_max = rlimit.rlim_cur = x;
00181          setrlimit(resource, &rlimit);
00182          return CLI_SUCCESS;
00183       } else {
00184          if (!getrlimit(resource, &rlimit)) {
00185             char printlimit[32];
00186             const char *desc;
00187             if (rlimit.rlim_max == RLIM_INFINITY)
00188                ast_copy_string(printlimit, "effectively unlimited", sizeof(printlimit));
00189             else
00190                snprintf(printlimit, sizeof(printlimit), "limited to %d", (int) rlimit.rlim_cur);
00191             desc = str2desc(a->argv[1]);
00192             ast_cli(a->fd, "%c%s (%s) is %s.\n", toupper(desc[0]), desc + 1, a->argv[1], printlimit);
00193          } else
00194             ast_cli(a->fd, "Could not retrieve resource limits for %s: %s\n", str2desc(a->argv[1]), strerror(errno));
00195          return CLI_SUCCESS;
00196       }
00197    }
00198 }
00199 
00200 static struct ast_cli_entry cli_ulimit =
00201    AST_CLI_DEFINE(handle_cli_ulimit, "Set or show process resource limits");
00202 
00203 static int unload_module(void)
00204 {
00205    return ast_cli_unregister(&cli_ulimit);
00206 }
00207 
00208 static int load_module(void)
00209 {
00210    return ast_cli_register(&cli_ulimit) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS;
00211 }
00212 
00213 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Resource limits");
00214 

Generated on Wed Aug 18 22:33:55 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7