aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Dokuchaev <danfe@FreeBSD.org>2023-07-26 14:10:34 +0000
committerAlexey Dokuchaev <danfe@FreeBSD.org>2023-07-26 14:10:34 +0000
commitc8bcf96c005b148e5a3074c53b6a5909958e37a4 (patch)
tree759c9867e9c3d1c2215b10c081e67854bb6005df
parent69d3a975f2d7523f765ba97f0d94f5e4f9080ca4 (diff)
downloadports-c8bcf96c005b148e5a3074c53b6a5909958e37a4.tar.gz
ports-c8bcf96c005b148e5a3074c53b6a5909958e37a4.zip
sysutils/wmmemfree: modernize, unbreak, undeprecate the port (+)
When I ported this dockapp 20 years ago, it was not uncommon to peek inside ``struct vmmeter'' and other kernel structures with kvm_read(3) to obtain various data (e.g. page counters). These interfaces had always been fragile and potentially unsafe (due to sgid-to-kmem requirement), so let's switch to sysctl(3) instead as it provides the same data via documented, stable API. Address another problem while here: the dockapp tried to update the window from the signal handler, and no Xlib function can be safely called within a signal handler*. Do as advised and only raise a "need update" flag upon receiving a signal, then gather new data and redraw the window in the main loop. This approach, however, cannot work without modifying process_events() because of the blocking nature of XNextEvent(3) -- put another select(2) call in front so it can relinquish control to the outer loop. [*] http://www-h.eng.cam.ac.uk/help/tpl/graphics/X/signals.html
-rw-r--r--sysutils/wmmemfree/Makefile12
-rw-r--r--sysutils/wmmemfree/files/mem_freebsd.c150
-rw-r--r--sysutils/wmmemfree/files/mem_freebsd.h32
-rw-r--r--sysutils/wmmemfree/files/patch-Makefile2
-rw-r--r--sysutils/wmmemfree/files/patch-dockapp.c39
-rw-r--r--sysutils/wmmemfree/files/patch-draw.c11
-rw-r--r--sysutils/wmmemfree/files/patch-wmmemfree.c43
7 files changed, 135 insertions, 154 deletions
diff --git a/sysutils/wmmemfree/Makefile b/sysutils/wmmemfree/Makefile
index 37ffa81f9091..e2119be083f7 100644
--- a/sysutils/wmmemfree/Makefile
+++ b/sysutils/wmmemfree/Makefile
@@ -4,21 +4,15 @@ PORTREVISION= 4
CATEGORIES= sysutils windowmaker
MASTER_SITES= SUNSITE/X11/xutils
-MAINTAINER= ports@FreeBSD.org
+MAINTAINER= danfe@FreeBSD.org
COMMENT= Memory and swap monitoring dockapp
-DEPRECATED= Broken on all supported FreeBSD releases for more than an year
-EXPIRATION_DATE= 2023-08-16
-BROKEN_FreeBSD_12= fails to compile: read_mem.c: invalid use of undefined type 'struct vmmeter'
-BROKEN_FreeBSD_13= fails to compile: read_mem.c: invalid use of undefined type 'struct vmmeter'
-BROKEN_FreeBSD_14= fails to compile: read_mem.c: invalid use of undefined type 'struct vmmeter'
-BROKEN_mips= fails to compile: mem_freebsd.c: storage size of 'vm' isn't known
-BROKEN_mips64= fails to compile: mem_freebsd.c: storage size of 'vm' isn't known
+LICENSE= GPLv2+
USES= localbase tar:bzip2 xorg
USE_XORG= x11 xext xpm
-PLIST_FILES= "@(,kmem,2555) bin/wmmemfree" man/man1/${PORTNAME}.1.gz
+PLIST_FILES= bin/${PORTNAME} man/man1/${PORTNAME}.1.gz
post-patch:
@${CP} ${FILESDIR}/mem_freebsd.* ${WRKSRC}
diff --git a/sysutils/wmmemfree/files/mem_freebsd.c b/sysutils/wmmemfree/files/mem_freebsd.c
index 5575ee31792c..a639a5d8157c 100644
--- a/sysutils/wmmemfree/files/mem_freebsd.c
+++ b/sysutils/wmmemfree/files/mem_freebsd.c
@@ -1,118 +1,76 @@
-/*
- * mem_freebsd.c - get memory status
- *
- * Copyright (C) 2003 Alexey Dokuchaev <danfe@regency.nsu.ru>
- * Parts are Copyright (C) 1993-2003 FreeBSD Project
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- */
-
#include <sys/types.h>
-#include <sys/vmmeter.h>
-#include <fcntl.h>
-#include <kvm.h>
-#include <nlist.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
+#include <sys/sysctl.h>
+#include <vm/vm_param.h>
#include <unistd.h>
-#include "mem_freebsd.h"
+long long int mem_total, mem_used, mem_buffers, mem_cached;
+long long int swp_total, swp_used;
-long long int mem_total, mem_used, mem_free, mem_buffers, mem_cached;
-long long int swp_total, swp_used, swp_free;
-
-static kvm_t *kd;
-struct nlist nlst[] = { {"_cnt"}, {"_bufspace"}, {0} };
+enum { total, active, laundry, wired, buffers, swap };
+int mib[swap - total + 1][4];
+/*
+ * Values below are in kilobytes: we don't need higher granulation,
+ * and it allows to keep numbers relatively small.
+ */
+unsigned int mem[swap - total];
+int pagesize;
void
-mem_init(void)
+mem_init()
{
- int pagesize;
-
- if (!(kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")))
- {
- perror("kvm_open");
- exit(1);
- }
+ size_t len = 4;
- kvm_nlist(kd, nlst);
+ /* Precache MIB name vectors for faster lookups later */
+ sysctlnametomib("vm.stats.vm.v_page_count", mib[total], &len);
+ sysctlnametomib("vm.stats.vm.v_active_count", mib[active], &len);
+ sysctlnametomib("vm.stats.vm.v_laundry_count", mib[laundry], &len);
+ sysctlnametomib("vm.stats.vm.v_wire_count", mib[wired], &len);
- if (!nlst[0].n_type)
- {
- perror("kvm_nlist");
- exit(1);
- }
+ len = 2;
+ sysctlnametomib("vfs.bufspace", mib[buffers], &len);
+ sysctlnametomib("vm.swap_info", mib[swap], &len);
- seteuid(getuid());
- setegid(getgid());
+ pagesize = getpagesize() / 1024;
+}
- if (geteuid() != getuid() || getegid() != getgid())
- {
- perror("sete?id");
- exit(1);
+static void
+get_swap_info()
+{
+ struct xswdev xsw;
+ size_t len = sizeof(xsw);
+ int n;
+
+ for (swp_total = swp_used = n = 0; ; ++n) {
+ mib[swap][2] = n;
+ if (sysctl(mib[swap], 3, &xsw, &len, NULL, 0) == -1)
+ break;
+ swp_total += pagesize * xsw.xsw_nblks;
+ swp_used += pagesize * xsw.xsw_used;
}
}
void
mem_getfree()
{
- struct vmmeter vm;
- struct kvm_swap sw;
- int bufspace = 0;
- unsigned long cnt_offset;
- unsigned long bufspace_offset;
-
- static int firsttime = 1;
- static time_t lasttime = 0;
- time_t curtime;
-
- if ((kvm_read(kd, nlst[0].n_value, &vm, sizeof(vm))
- != sizeof(vm)) ||
- (kvm_read(kd, nlst[1].n_value, &bufspace, sizeof(bufspace))
- != sizeof(bufspace)))
- {
- perror("kvm_read");
- exit(1);
- }
+ size_t len = 4;
+ int n;
- mem_total = vm.v_page_count;
- mem_free = vm.v_free_count;
- mem_used = mem_total - mem_free;
- mem_cached = vm.v_cache_count;
- mem_buffers = bufspace / vm.v_page_size;
+ for (n = 0; n < buffers - total; ++n)
+ sysctl(mib[n], 4, &mem[n], &len, NULL, 0);
+ sysctl(mib[buffers], 2, &mem[buffers], &len, NULL, 0);
/*
- * Only calculate when first time or when changes took place.
- * Do not call it more than 1 time per 2 seconds; otherwise
- * it can eat up to 50% of CPU time on heavy swap activity.
+ * See the following links for explanation which pages we consider
+ * free and used (cf. Linux vs. FreeBSD):
+ * https://unix.stackexchange.com/questions/14102/real-memory-usage
+ * https://unix.stackexchange.com/questions/134862/what-do-the-different-memory-counters-in-freebsd-mean
*/
-
- curtime = time(NULL);
-
- if (firsttime || curtime > lasttime + 5)
- {
- if (kvm_getswapinfo(kd, &sw, 1, 0) >= 0 &&
- sw.ksw_total)
- {
- swp_total = sw.ksw_total;
- swp_used = sw.ksw_used;
- swp_free = swp_total - swp_used;
- }
- firsttime = 0;
- lasttime = curtime;
- }
+ mem_total = pagesize * mem[total];
+ /* On FreeBSD, "Laundry" had replaced "Cache" in November 2016 */
+ mem_cached = pagesize * mem[laundry];
+ mem_buffers = mem[buffers] / 1024;
+ mem_used = pagesize * (mem[active] + mem[wired]);
+ mem_used += mem_cached + mem_buffers;
+
+ get_swap_info();
}
diff --git a/sysutils/wmmemfree/files/mem_freebsd.h b/sysutils/wmmemfree/files/mem_freebsd.h
deleted file mode 100644
index d0f86dc328a5..000000000000
--- a/sysutils/wmmemfree/files/mem_freebsd.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * mem_freebsd.h
- *
- * Copyright (C) 2003 Alexey Dokuchaev <danfe@regency.nsu.ru>
- * Parts are Copyright (C) 1993-2003 FreeBSD Project
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __MEM_FREEBSD_H__
-#define __MEM_FREEBSD_H__
-
-extern long long int mem_total, mem_used;
-extern long long int mem_shared, mem_buffers, mem_cached;
-extern long long int swp_total, swp_used;
-
-void mem_init();
-void mem_getfree();
-
-#endif /* __MEM_FREEBSD_H__ */
diff --git a/sysutils/wmmemfree/files/patch-Makefile b/sysutils/wmmemfree/files/patch-Makefile
index 26f34c806042..0b775f3fc0b6 100644
--- a/sysutils/wmmemfree/files/patch-Makefile
+++ b/sysutils/wmmemfree/files/patch-Makefile
@@ -18,7 +18,7 @@
INST=install
MANUAL=$(PROG).1
-LIBS=-L/usr/X11R6/lib -lX11 -lXext -lXpm
-+LIBS+=-lX11 -lXext -lXpm -lkvm
++LIBS+=-lX11 -lXext -lXpm
all: $(PROG)
diff --git a/sysutils/wmmemfree/files/patch-dockapp.c b/sysutils/wmmemfree/files/patch-dockapp.c
new file mode 100644
index 000000000000..94d51d597205
--- /dev/null
+++ b/sysutils/wmmemfree/files/patch-dockapp.c
@@ -0,0 +1,39 @@
+--- dockapp.c.orig 2003-03-22 18:30:01 UTC
++++ dockapp.c
+@@ -41,7 +41,7 @@
+ #define WINDOW_HEIGHT 64
+
+ Display *display;
+-int screen;
++int screen, x11fd;
+ Window iconwindow, window, mapwindow;
+ Colormap colormap;
+ GC gc;
+@@ -114,6 +114,7 @@ void make_window()
+ fprintf(stderr, "Could not open display %s\n", opt_display);
+ exit(1);
+ }
++ x11fd = ConnectionNumber(display);
+ screen = DefaultScreen(display);
+ screenwidth = DisplayWidth(display, screen);
+ screenheight = DisplayHeight(display, screen);
+@@ -254,6 +255,19 @@ void process_events()
+ XEvent event;
+ int winx, winy;
+
++ XSync(display, False);
++ if(!XPending(display))
++ {
++ struct timeval timeout;
++ fd_set readset;
++ const int milliseconds = 200;
++ timeout.tv_sec = milliseconds / 1000;
++ timeout.tv_usec = (milliseconds % 1000) * 1000;
++ FD_ZERO(&readset);
++ FD_SET(x11fd, &readset);
++ if(select(x11fd + 1, &readset, NULL, NULL, &timeout) <= 0)
++ return;
++ }
+ XNextEvent(display, &event);
+ switch(event.type)
+ {
diff --git a/sysutils/wmmemfree/files/patch-draw.c b/sysutils/wmmemfree/files/patch-draw.c
deleted file mode 100644
index 1e107ac48a6e..000000000000
--- a/sysutils/wmmemfree/files/patch-draw.c
+++ /dev/null
@@ -1,11 +0,0 @@
---- draw.c.orig Fri Apr 11 12:47:47 2003
-+++ draw.c Fri Apr 11 12:47:54 2003
-@@ -24,7 +24,7 @@
-
- #include "dockapp.h"
- #include "draw.h"
--#include "mem_linux.h"
-+#include "mem_freebsd.h"
- #include "options.h"
-
- void draw_window()
diff --git a/sysutils/wmmemfree/files/patch-wmmemfree.c b/sysutils/wmmemfree/files/patch-wmmemfree.c
index 62f224511132..0193cc03bea5 100644
--- a/sysutils/wmmemfree/files/patch-wmmemfree.c
+++ b/sysutils/wmmemfree/files/patch-wmmemfree.c
@@ -1,10 +1,27 @@
---- wmmemfree.c.orig Fri Apr 11 12:48:52 2003
-+++ wmmemfree.c Fri Apr 11 12:50:05 2003
-@@ -43,10 +43,11 @@
+--- wmmemfree.c.orig 2003-03-21 20:47:14 UTC
++++ wmmemfree.c
+@@ -27,15 +27,18 @@
+ #include "draw.h"
+ #include "options.h"
+
++void mem_init();
++
+ int argc;
+ char **argv;
+ int exitloop = 0;
++volatile sig_atomic_t need_update = 0;
+
+ void handle_timer(int sig)
{
- struct itimerval tv;
+ if(sig == SIGALRM)
+ {
+- draw_window();
++ need_update = 1;
+ }
+ }
+
+@@ -45,8 +48,8 @@ void start_timer()
-+ mem_init();
tv.it_value.tv_sec = 2; /* give 2 seconds for safety */
tv.it_value.tv_usec = 0;
- tv.it_interval.tv_sec = 0;
@@ -14,3 +31,19 @@
signal(SIGALRM, handle_timer);
setitimer(ITIMER_REAL, &tv, NULL);
}
+@@ -69,9 +72,15 @@ int main(int carg, char **varg)
+ argv = varg;
+ parse_args();
+ make_window();
++ mem_init();
+ start_timer();
+ while(!exitloop)
+ {
++ if(need_update)
++ {
++ draw_window();
++ need_update = 0;
++ }
+ process_events();
+ }
+ stop_timer();