Hello
Currently init script sets resource limits globally. However it is not very convenient for many applications, as some of the limits can be potentially dangerous and should be assigned per service instead of globally. The suggested patch below enables "setrlimit" configuration option per service definition (in init.rc).
Hope it would be found usefull.
Regards
Valeri
diff --git a/init/init.c b/init/init.c
index 1ee88a7..65b8f9f 100755
--- a/init/init.c
+++ b/init/init.c
@@ -283,6 +283,25 @@ void service_start(struct service *svc, const char *dynamic_args)
zap_stdio();
}
+ /* Change resource limits before setting UID/GID */
+ if (svc->nrlims) {
+ int n;
+ for (n = 0; n < svc->nrlims; n++) {
+ NOTICE("service[%s]:setrlimit: %d: cur=%lld; max=%lld\n",
+ svc->name,
+ svc->rlims[n].resource,
+ (long long)svc->rlims[n].rlim.rlim_cur,
+ (long long)svc->rlims[n].rlim.rlim_max);
+ if (setrlimit(svc->rlims[n].resource, &svc->rlims[n].rlim)) {
+ ERROR("cannot setrlimit(%d,%lld,%lld): %s\n",
+ svc->rlims[n].resource,
+ (long long)svc->rlims[n].rlim.rlim_cur,
+ (long long)svc->rlims[n].rlim.rlim_max,
+ strerror(errno));
+ }
+ }
+ }
+
#if 0
for (n = 0; svc->args[n]; n++) {
INFO("args[%d] = '%s'\n", n, svc->args[n]);
diff --git a/init/init.h b/init/init.h
index 58bbbfe..a5e7d80 100644
--- a/init/init.h
+++ b/init/init.h
@@ -20,6 +20,7 @@
#include <cutils/list.h>
#include <sys/stat.h>
+#include <sys/resource.h>
void handle_control_message(const char *msg, const char *arg);
@@ -77,6 +78,13 @@ struct svcenvinfo {
#define COMMAND_RETRY_TIMEOUT 5
+#define SVC_MAX_RLIMITS 32
+
+struct service_rlim {
+ int resource;
+ struct rlimit rlim;
+};
+
struct service {
/* list of all services */
struct listnode slist;
@@ -112,6 +120,9 @@ struct service {
int ioprio_class;
int ioprio_pri;
+ int nrlims;
+ struct service_rlim rlims[SVC_MAX_RLIMITS];
+
int nargs;
/* "MUST BE AT THE END OF THE STRUCT" */
char *args[1];
diff --git a/init/init_parser.c b/init/init_parser.c
index f538450..a83e1db 100644
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -806,6 +806,18 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args
}
#endif
break;
+ case K_setrlimit:
+ if (nargs != 4) {
+ parse_error(state, "setrlimit option requires 3 arguments\n");
+ } else if (svc->nrlims == SVC_MAX_RLIMITS -1) {
+ parse_error(state, "setrlimit option must not be used over %d times\n", SVC_MAX_RLIMITS);
+ } else {
+ int n = svc->nrlims++;
+ svc->rlims[n].resource = atoi(args[1]);
+ svc->rlims[n].rlim.rlim_cur = atoi(args[2]);
+ svc->rlims[n].rlim.rlim_max = atoi(args[3]);
+ }
+ break;
default:
parse_error(state, "invalid option '%s'\n", args[0]);
diff --git a/init/readme.txt b/init/readme.txt
index df524a6..d8e8e26 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -100,6 +100,10 @@ class <name>
onrestart
Execute a Command (see below) when service restarts.
+setrlimit <resource> <cur> <max>
+ Sets service process resource limit. There could be up to 32 different
+ limits.
+
Triggers
--------
Triggers are strings which can be used to match certain kinds