Suggestion for service resource limit control

66 views
Skip to first unread message

Valeri Atamaniouk

unread,
Oct 5, 2012, 4:33:12 AM10/5/12
to android-...@googlegroups.com
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

Glenn Kasten

unread,
Oct 5, 2012, 11:45:58 AM10/5/12
to android-...@googlegroups.com
Thank you for your suggestion, however I want to remind everyone of the process for making contributions to AOSP:

0. android-platform is for general discussion 
1. specific working proposals are on android-contrib
2. discuss on android-contrib
3. after there is consensus (or the patch is so minor it doesn't need discussion),
    upload the patch to AOSP Gerrit instance
4. patch is reviewed etc. and submitted as appropriate.
    It can get stuck here for a while, this is a known problem.

We don't upload patches to here (android-platform) or android-contrib for several reasons,
but one major one is that we need a Contributor License Grant,
and that can't be done for patches uploaded by email.

In this particular case (service process resource limit), there is a pending CL
in review and it needs some attention :-(
Reply all
Reply to author
Forward
0 new messages