git: c8bcf96c005b - main - sysutils/wmmemfree: modernize, unbreak, undeprecate the port (+)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 26 Jul 2023 14:11:50 UTC
The branch main has been updated by danfe: URL: https://cgit.FreeBSD.org/ports/commit/?id=c8bcf96c005b148e5a3074c53b6a5909958e37a4 commit c8bcf96c005b148e5a3074c53b6a5909958e37a4 Author: Alexey Dokuchaev <danfe@FreeBSD.org> AuthorDate: 2023-07-26 14:10:34 +0000 Commit: Alexey Dokuchaev <danfe@FreeBSD.org> CommitDate: 2023-07-26 14:10:34 +0000 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 --- sysutils/wmmemfree/Makefile | 12 +-- sysutils/wmmemfree/files/mem_freebsd.c | 150 +++++++++++------------------ sysutils/wmmemfree/files/mem_freebsd.h | 32 ------ sysutils/wmmemfree/files/patch-Makefile | 2 +- sysutils/wmmemfree/files/patch-dockapp.c | 39 ++++++++ sysutils/wmmemfree/files/patch-draw.c | 11 --- sysutils/wmmemfree/files/patch-wmmemfree.c | 43 ++++++++- 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();