Fri Jul 24 00:41:02 2009

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

Generated on Fri Jul 24 00:41:02 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7