res_limit.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Resource limits
  5. *
  6. * Copyright (c) 2006 Tilghman Lesher. All rights reserved.
  7. *
  8. * Tilghman Lesher <res_limit_200607@the-tilghman.com>
  9. *
  10. * This code is released by the author with no restrictions on usage.
  11. *
  12. */
  13. /*! \file
  14. *
  15. * \brief Resource limits
  16. *
  17. * \author Tilghman Lesher <res_limit_200607@the-tilghman.com>
  18. */
  19. /*** MODULEINFO
  20. <support_level>core</support_level>
  21. ***/
  22. #include "asterisk.h"
  23. #include <ctype.h>
  24. #include <sys/time.h>
  25. #include <sys/resource.h>
  26. #include "asterisk/module.h"
  27. #include "asterisk/cli.h"
  28. /* Find proper rlimit for virtual memory */
  29. #ifdef RLIMIT_AS
  30. #define VMEM_DEF RLIMIT_AS
  31. #else
  32. #ifdef RLIMIT_VMEM
  33. #define VMEM_DEF RLIMIT_VMEM
  34. #endif
  35. #endif
  36. static const struct limits {
  37. int resource;
  38. char limit[3];
  39. char desc[40];
  40. char clicmd[15];
  41. } limits[] = {
  42. { RLIMIT_CPU, "-t", "cpu time", "time" },
  43. { RLIMIT_FSIZE, "-f", "file size" , "file" },
  44. { RLIMIT_DATA, "-d", "program data segment", "data" },
  45. { RLIMIT_STACK, "-s", "program stack size", "stack" },
  46. { RLIMIT_CORE, "-c", "core file size", "core" },
  47. #ifdef RLIMIT_RSS
  48. { RLIMIT_RSS, "-m", "resident memory", "memory" },
  49. { RLIMIT_MEMLOCK, "-l", "amount of memory locked into RAM", "locked" },
  50. #endif
  51. #ifdef RLIMIT_NPROC
  52. { RLIMIT_NPROC, "-u", "number of processes", "processes" },
  53. #endif
  54. { RLIMIT_NOFILE, "-n", "number of file descriptors", "descriptors" },
  55. #ifdef VMEM_DEF
  56. { VMEM_DEF, "-v", "virtual memory", "virtual" },
  57. #endif
  58. };
  59. static int str2limit(const char *string)
  60. {
  61. size_t i;
  62. for (i = 0; i < ARRAY_LEN(limits); i++) {
  63. if (!strcasecmp(string, limits[i].clicmd))
  64. return limits[i].resource;
  65. }
  66. return -1;
  67. }
  68. static const char *str2desc(const char *string)
  69. {
  70. size_t i;
  71. for (i = 0; i < ARRAY_LEN(limits); i++) {
  72. if (!strcmp(string, limits[i].clicmd))
  73. return limits[i].desc;
  74. }
  75. return "<unknown>";
  76. }
  77. static char *complete_ulimit(struct ast_cli_args *a)
  78. {
  79. int which = 0, i;
  80. int wordlen = strlen(a->word);
  81. if (a->pos > 1)
  82. return NULL;
  83. for (i = 0; i < ARRAY_LEN(limits); i++) {
  84. if (!strncasecmp(limits[i].clicmd, a->word, wordlen)) {
  85. if (++which > a->n)
  86. return ast_strdup(limits[i].clicmd);
  87. }
  88. }
  89. return NULL;
  90. }
  91. static char *handle_cli_ulimit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  92. {
  93. int resource;
  94. struct rlimit rlimit = { 0, 0 };
  95. switch (cmd) {
  96. case CLI_INIT:
  97. e->command = "ulimit";
  98. e->usage =
  99. "Usage: ulimit {data|"
  100. #ifdef RLIMIT_RSS
  101. "limit|"
  102. #endif
  103. "file|"
  104. #ifdef RLIMIT_RSS
  105. "memory|"
  106. #endif
  107. "stack|time|"
  108. #ifdef RLIMIT_NPROC
  109. "processes|"
  110. #endif
  111. #ifdef VMEM_DEF
  112. "virtual|"
  113. #endif
  114. "core|descriptors} [<num>]\n"
  115. " Shows or sets the corresponding resource limit.\n"
  116. " data Process data segment [readonly]\n"
  117. #ifdef RLIMIT_RSS
  118. " lock Memory lock size [readonly]\n"
  119. #endif
  120. " file File size\n"
  121. #ifdef RLIMIT_RSS
  122. " memory Process resident memory [readonly]\n"
  123. #endif
  124. " stack Process stack size [readonly]\n"
  125. " time CPU usage [readonly]\n"
  126. #ifdef RLIMIT_NPROC
  127. " processes Child processes\n"
  128. #endif
  129. #ifdef VMEM_DEF
  130. " virtual Process virtual memory [readonly]\n"
  131. #endif
  132. " core Core dump file size\n"
  133. " descriptors Number of file descriptors\n";
  134. return NULL;
  135. case CLI_GENERATE:
  136. return complete_ulimit(a);
  137. }
  138. if (a->argc > 3)
  139. return CLI_SHOWUSAGE;
  140. if (a->argc == 1) {
  141. char arg2[15];
  142. const char * const newargv[2] = { "ulimit", arg2 };
  143. for (resource = 0; resource < ARRAY_LEN(limits); resource++) {
  144. struct ast_cli_args newArgs = { .argv = newargv, .argc = 2 };
  145. ast_copy_string(arg2, limits[resource].clicmd, sizeof(arg2));
  146. handle_cli_ulimit(e, CLI_HANDLER, &newArgs);
  147. }
  148. return CLI_SUCCESS;
  149. } else {
  150. resource = str2limit(a->argv[1]);
  151. if (resource == -1) {
  152. ast_cli(a->fd, "Unknown resource\n");
  153. return CLI_FAILURE;
  154. }
  155. if (a->argc == 3) {
  156. int x;
  157. #ifdef RLIMIT_NPROC
  158. if (resource != RLIMIT_NOFILE && resource != RLIMIT_CORE && resource != RLIMIT_NPROC && resource != RLIMIT_FSIZE) {
  159. #else
  160. if (resource != RLIMIT_NOFILE && resource != RLIMIT_CORE && resource != RLIMIT_FSIZE) {
  161. #endif
  162. ast_cli(a->fd, "Resource not permitted to be set\n");
  163. return CLI_FAILURE;
  164. }
  165. sscanf(a->argv[2], "%30d", &x);
  166. rlimit.rlim_max = rlimit.rlim_cur = x;
  167. setrlimit(resource, &rlimit);
  168. return CLI_SUCCESS;
  169. } else {
  170. if (!getrlimit(resource, &rlimit)) {
  171. char printlimit[32];
  172. const char *desc;
  173. if (rlimit.rlim_max == RLIM_INFINITY)
  174. ast_copy_string(printlimit, "effectively unlimited", sizeof(printlimit));
  175. else
  176. snprintf(printlimit, sizeof(printlimit), "limited to %d", (int) rlimit.rlim_cur);
  177. desc = str2desc(a->argv[1]);
  178. ast_cli(a->fd, "%c%s (%s) is %s.\n", toupper(desc[0]), desc + 1, a->argv[1], printlimit);
  179. } else
  180. ast_cli(a->fd, "Could not retrieve resource limits for %s: %s\n", str2desc(a->argv[1]), strerror(errno));
  181. return CLI_SUCCESS;
  182. }
  183. }
  184. }
  185. static struct ast_cli_entry cli_ulimit =
  186. AST_CLI_DEFINE(handle_cli_ulimit, "Set or show process resource limits");
  187. static int unload_module(void)
  188. {
  189. return ast_cli_unregister(&cli_ulimit);
  190. }
  191. static int load_module(void)
  192. {
  193. return ast_cli_register(&cli_ulimit) ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
  194. }
  195. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Resource limits");