From 87d55ae018f4298fed4c223c5f8fca9750b6d868 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Wed, 26 Jan 2022 07:51:17 +0100
Subject: [PATCH 31/31] procd: add service measurement

Signed-off-by: John Crispin <john@phrozen.org>
---
 ...service-resource-measurement-support.patch | 165 ++++++++++++++++++
 1 file changed, 165 insertions(+)
 create mode 100644 package/system/procd/patches/0002-add-service-resource-measurement-support.patch

diff --git a/package/system/procd/patches/0002-add-service-resource-measurement-support.patch b/package/system/procd/patches/0002-add-service-resource-measurement-support.patch
new file mode 100644
index 0000000000..de3e767eac
--- /dev/null
+++ b/package/system/procd/patches/0002-add-service-resource-measurement-support.patch
@@ -0,0 +1,165 @@
+From b34b9a29cff6de4487586cae6d09bac45b9a9e59 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Wed, 26 Jan 2022 07:43:55 +0100
+Subject: [PATCH] add service resource measurement support
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ service/instance.c | 106 ++++++++++++++++++++++++++++++++++++++++++++-
+ service/instance.h |   1 +
+ service/service.c  |   1 +
+ 3 files changed, 107 insertions(+), 1 deletion(-)
+
+diff --git a/service/instance.c b/service/instance.c
+index 9c74265..bf2b597 100644
+--- a/service/instance.c
++++ b/service/instance.c
+@@ -28,6 +28,10 @@
+ #include <unistd.h>
+ #define SYSLOG_NAMES
+ #include <syslog.h>
++#include <glob.h>
++#include <regex.h>
++#include <ctype.h>
++#include <sys/sysinfo.h>
+ 
+ #include <libubox/md5.h>
+ 
+@@ -189,6 +193,102 @@ static const struct rlimit_name rlimit_names[] = {
+ 	{ NULL, 0 }
+ };
+ 
++static regex_t pat_vmdata, pat_vmstk;
++struct sysinfo info;
++long systick;
++
++static void __attribute__((constructor))
++measure_init()
++{
++	regcomp(&pat_vmdata, "VmData:[ \t]*([0-9]*) kB", REG_EXTENDED);
++	regcomp(&pat_vmstk, "VmStk:[ \t]*([0-9]*) kB", REG_EXTENDED);
++}
++
++static char *
++strnchr(char *buf, int c, int i)
++{
++	while (*buf && i) {
++		buf = strchr(buf, c);
++		buf++;
++		i--;
++	}
++	return buf;
++}
++
++void
++measure_start(void)
++{
++	sysinfo(&info);
++	systick = sysconf(_SC_CLK_TCK);
++}
++
++static int
++measure_process(struct blob_buf *b, pid_t pid)
++{
++	int fd;
++	char buffer[512] = "";
++	ssize_t rxed;
++	regmatch_t matches[2];
++	glob_t gl;
++	size_t i;
++	char *ch;
++	uint32_t fdcount = 0;
++	uint32_t mem = 0;
++
++	snprintf(buffer, sizeof(buffer), "/proc/%i/fd/*", (int)pid);
++
++	if (glob(buffer, GLOB_NOESCAPE | GLOB_MARK, NULL, &gl))
++		return -1;
++
++	for (i = 0; i < gl.gl_pathc; i++)
++		if (isdigit(basename(gl.gl_pathv[i])[0]))
++			fdcount = fdcount + 1;
++	globfree(&gl);
++	blobmsg_add_u32(b, "fds", fdcount);
++
++	snprintf(buffer, sizeof(buffer), "/proc/%i/stat", (int)pid);
++	fd = open(buffer, O_RDONLY);
++	if (fd == -1)
++		return -1;
++
++	rxed = read(fd, buffer, sizeof(buffer) - 1);
++	close(fd);
++	if (rxed == -1)
++		return -1;
++
++	buffer[rxed] = 0;
++
++	ch = strnchr(buffer, ' ', 14);
++	if (ch)
++		blobmsg_add_u64(b, "load", atoll(ch));
++
++	ch = strnchr(buffer, ' ', 21);
++	if (ch)
++		blobmsg_add_u64(b, "age", info.uptime - atol(ch) / systick);
++
++	snprintf(buffer, sizeof(buffer), "/proc/%i/status", (int)pid);
++	fd = open(buffer, O_RDONLY);
++	if (fd == -1)
++		return -1;
++
++	rxed = read(fd, buffer, sizeof(buffer) - 1);
++	close(fd);
++	if (rxed == -1)
++		return -1;
++
++	buffer[rxed] = 0;
++
++	if (!regexec(&pat_vmdata, buffer, 2, matches, 0))
++		mem += atoi(buffer + matches[1].rm_so) * 1024;
++
++	if (!regexec(&pat_vmstk, buffer, 2, matches, 0))
++		mem += atoi(buffer + matches[1].rm_so) * 1024;
++
++	blobmsg_add_u64(b, "meminfo", mem);
++
++	return 0;
++}
++
+ static void closefd(int fd)
+ {
+ 	if (fd > STDERR_FILENO)
+@@ -1795,5 +1896,8 @@ void instance_dump(struct blob_buf *b, struct service_instance *in, int verbose)
+ 		blobmsg_close_table(b, r);
+ 	}
+ 
++	if (in->proc.pending)
++		measure_process(b, in->proc.pid);
++
+ 	blobmsg_close_table(b, i);
+ }
+diff --git a/service/instance.h b/service/instance.h
+index 15eb997..1606eed 100644
+--- a/service/instance.h
++++ b/service/instance.h
+@@ -122,5 +122,6 @@ void instance_update(struct service_instance *in, struct service_instance *in_ne
+ void instance_init(struct service_instance *in, struct service *s, struct blob_attr *config);
+ void instance_free(struct service_instance *in);
+ void instance_dump(struct blob_buf *b, struct service_instance *in, int debug);
++void measure_start(void);
+ 
+ #endif
+diff --git a/service/service.c b/service/service.c
+index bb3e121..9cd8886 100644
+--- a/service/service.c
++++ b/service/service.c
+@@ -497,6 +497,7 @@ service_handle_list(struct ubus_context *ctx, struct ubus_object *obj,
+ 	if (tb[SERVICE_LIST_ATTR_NAME])
+ 		name = blobmsg_get_string(tb[SERVICE_LIST_ATTR_NAME]);
+ 
++	measure_start();
+ 	blob_buf_init(&b, 0);
+ 	avl_for_each_element(tree, s, avl) {
+ 		if (name && strcmp(s->name, name) != 0)
+-- 
+2.25.1
+
-- 
2.25.1

