Browse Source
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`).android-5
Alexander Clouter
6 years ago
committed by
Fredrik Fornwall
1 changed files with 145 additions and 0 deletions
@ -0,0 +1,145 @@ |
|||
diff --git a/lib/os_mon/c_src/cpu_sup.c b/lib/os_mon/c_src/cpu_sup.c
|
|||
index 17ef48c26e..b63b183c69 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,23 @@ 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: (unsigned int)(return info.loads[0] / 256);
|
|||
+ case AVG5: (unsigned int)(return info.loads[1] / 256);
|
|||
+ case AVG15: (unsigned int)(return info.loads[2] / 256);
|
|||
+ case NPROCS: return info.procs;
|
|||
+ }
|
|||
+ sendi((unsigned int)(avgs[idx] * 256));
|
|||
+
|
|||
+ return -1;
|
|||
+}
|
|||
+
|
|||
static cpu_t *read_procstat(FILE *fp, cpu_t *cpu) { |
|||
char buffer[BUFFERSIZE]; |
|||
|
|||
@@ -357,8 +381,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 +407,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; |
Loading…
Reference in new issue