LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File 0452-Make-Erlang-s-cpu_sup-function-better-on-Android.patch of Package erlang (Project home:Ledest:erlang:20)

From f2ca9d9cb14527fb5dd3016cbccd45355cc2a6c7 Mon Sep 17 00:00:00 2001
From: Alexander Clouter <alex@digriz.org.uk>
Date: Thu, 27 Sep 2018 20:33:16 +0100
Subject: [PATCH 2/2] Make Erlang's cpu_sup function better on Android

Due to `/proc` restrictions in newer Android releases enforced by SELinux, Erlang needs a fix so that it can get some basic CPU stats (use the `sysinfo` syscall rather than reading `/proc/loadavg`).
---
 lib/os_mon/c_src/cpu_sup.c | 50 ++++++++++++++++++++++++++++++++++++++++------
 lib/os_mon/src/cpu_sup.erl | 26 ++++++++++++++----------
 2 files changed, 59 insertions(+), 17 deletions(-)

diff --git a/lib/os_mon/c_src/cpu_sup.c b/lib/os_mon/c_src/cpu_sup.c
index 17ef48c26e..c96a5c9f7c 100644
--- a/lib/os_mon/c_src/cpu_sup.c
+++ b/lib/os_mon/c_src/cpu_sup.c
@@ -152,6 +152,8 @@ static void util_measure(unsigned int **result_vec, int *result_sz);
 
 #if defined(__sun__)
 static unsigned int misc_measure(char* name);
+#elif defined(__linux__)
+static unsigned int misc_measure(char cmd);
 #endif
 static void sendi(unsigned int data);
 static void sendv(unsigned int data[], int ints);
@@ -231,6 +233,11 @@ int main(int argc, char** argv) {
     case AVG1:		sendi(misc_measure("avenrun_1min"));		break;
     case AVG5:		sendi(misc_measure("avenrun_5min"));		break;
     case AVG15:		sendi(misc_measure("avenrun_15min"));		break;
+#elif defined(__linux__)
+    case NPROCS:
+    case AVG1:
+    case AVG5:
+    case AVG15:		sendi(misc_measure(cmd));			break;
 #elif defined(__OpenBSD__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__) || defined(__DragonFly__)
     case NPROCS:	bsd_count_procs();				break;
     case AVG1:		bsd_loadavg(0);					break;
@@ -238,7 +245,7 @@ int main(int argc, char** argv) {
     case AVG15:		bsd_loadavg(2);					break;
 #endif
 #if defined(__sun__) || defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__)
-    case UTIL:		util_measure(&rv,&sz); 	sendv(rv, sz);		break;
+    case UTIL:		util_measure(&rv,&sz); sendv(rv, sz);		break;
 #endif
     case QUIT:		free((void*)rv); return 0;
     default:		error("Bad command");				break;
@@ -329,6 +336,22 @@ static void bsd_count_procs(void) {
 
 #if defined(__linux__)
 
+static unsigned int misc_measure(char cmd) {
+    struct sysinfo info;
+
+    if (sysinfo(&info))
+        error(strerror(errno));
+
+    switch (cmd) {
+    case AVG1:	 	return (unsigned int)(info.loads[0] / 256);
+    case AVG5:	 	return (unsigned int)(info.loads[1] / 256);
+    case AVG15: 	return (unsigned int)(info.loads[2] / 256);
+    case NPROCS:	return info.procs;
+    }
+
+    return -1;
+}
+
 static cpu_t *read_procstat(FILE *fp, cpu_t *cpu) {
     char buffer[BUFFERSIZE];
 
@@ -357,8 +380,24 @@ static void util_measure(unsigned int **result_vec, int *result_sz) {
     FILE *fp;
     unsigned int *rv = NULL;
     cpu_t cpu;
- 
+
+    rv = *result_vec;
+    rv[0] = no_of_cpus;
+
     if ( (fp = fopen(PROCSTAT,"r")) == NULL) {
+        if (errno == EACCES) { /* SELinux */
+            rv[1] = 1; /* just the cpu id */
+            ++rv; /* first value is number of cpus */
+            ++rv; /* second value is number of entries */
+            for (i = 0; i < no_of_cpus; ++i) {
+                rv[0] = CU_CPU_ID;
+                rv[1] = i;
+	        rv += 1*2;
+            }
+            *result_sz = 2 + 2*1 * no_of_cpus;
+            return;
+        }
+
 	/* Check if procfs is mounted,
 	 *  otherwise:
 	 *  try and try again, bad procsfs.
@@ -367,20 +406,19 @@ static void util_measure(unsigned int **result_vec, int *result_sz) {
 	return;
     }
 
-	/*ignore read*/
+    /*ignore read*/
     if (fgets(buffer, BUFFERSIZE, fp) == NULL) {
 	*result_sz = 0;
 	return;
     }
-    rv = *result_vec; 
-    rv[0] = no_of_cpus;
+
     rv[1] = CU_VALUES;
     ++rv; /* first value is number of cpus */
     ++rv; /* second value is number of entries */
 
     for (i = 0; i < no_of_cpus; ++i) {
 	read_procstat(fp, &cpu);
-	      
+
 	rv[ 0] = CU_CPU_ID;    rv[ 1] = cpu.id;
 	rv[ 2] = CU_USER;      rv[ 3] = cpu.user;
 	rv[ 4] = CU_NICE_USER; rv[ 5] = cpu.nice_user;
diff --git a/lib/os_mon/src/cpu_sup.erl b/lib/os_mon/src/cpu_sup.erl
index 81e049ef22..ba2d89313e 100644
--- a/lib/os_mon/src/cpu_sup.erl
+++ b/lib/os_mon/src/cpu_sup.erl
@@ -220,17 +220,21 @@ code_change(_OldVsn, State, _Extra) ->
 %% internal functions 
 %%----------------------------------------------------------------------
 
-get_uint32_measurement(Request, #internal{os_type = {unix, linux}}) ->
-    {ok,F} = file:open("/proc/loadavg",[read,raw]),
-    {ok,D} = file:read_line(F),
-    ok = file:close(F),
-    {ok,[Load1,Load5,Load15,_PRun,PTotal],_} = io_lib:fread("~f ~f ~f ~d/~d", D),
-    case Request of
-	?avg1  -> sunify(Load1);
-	?avg5  -> sunify(Load5);
-	?avg15 -> sunify(Load15);
-	?ping -> 4711;
-	?nprocs -> PTotal
+get_uint32_measurement(Request, #internal{port = P, os_type = {unix, linux}}) ->
+    case file:open("/proc/loadavg",[read,raw]) of
+        {ok,F} ->
+            {ok,D} = file:read_line(F),
+            ok = file:close(F),
+            {ok,[Load1,Load5,Load15,_PRun,PTotal],_} = io_lib:fread("~f ~f ~f ~d/~d", D),
+            case Request of
+                ?avg1  -> sunify(Load1);
+                ?avg5  -> sunify(Load5);
+                ?avg15 -> sunify(Load15);
+                ?ping -> 4711;
+                ?nprocs -> PTotal
+            end;
+        {error,_} ->
+            port_server_call(P, Request)
     end;
 get_uint32_measurement(Request, #internal{port = P, os_type = {unix, Sys}}) when
 								Sys == sunos;
-- 
2.16.4