mirror of
https://git.freebsd.org/ports.git
synced 2025-07-18 17:59:20 -04:00
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
This commit is contained in:
parent
69d3a975f2
commit
c8bcf96c00
7 changed files with 134 additions and 153 deletions
|
@ -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}
|
||||
|
|
|
@ -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;
|
||||
size_t len = 4;
|
||||
|
||||
if (!(kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")))
|
||||
{
|
||||
perror("kvm_open");
|
||||
exit(1);
|
||||
}
|
||||
/* 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);
|
||||
|
||||
kvm_nlist(kd, nlst);
|
||||
len = 2;
|
||||
sysctlnametomib("vfs.bufspace", mib[buffers], &len);
|
||||
sysctlnametomib("vm.swap_info", mib[swap], &len);
|
||||
|
||||
if (!nlst[0].n_type)
|
||||
{
|
||||
perror("kvm_nlist");
|
||||
exit(1);
|
||||
}
|
||||
pagesize = getpagesize() / 1024;
|
||||
}
|
||||
|
||||
seteuid(getuid());
|
||||
setegid(getgid());
|
||||
static void
|
||||
get_swap_info()
|
||||
{
|
||||
struct xswdev xsw;
|
||||
size_t len = sizeof(xsw);
|
||||
int n;
|
||||
|
||||
if (geteuid() != getuid() || getegid() != getgid())
|
||||
{
|
||||
perror("sete?id");
|
||||
exit(1);
|
||||
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;
|
||||
size_t len = 4;
|
||||
int n;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
get_swap_info();
|
||||
}
|
||||
|
|
|
@ -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__ */
|
|
@ -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)
|
||||
|
||||
|
|
39
sysutils/wmmemfree/files/patch-dockapp.c
Normal file
39
sysutils/wmmemfree/files/patch-dockapp.c
Normal file
|
@ -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)
|
||||
{
|
|
@ -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()
|
|
@ -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 @@
|
||||
{
|
||||
struct itimerval tv;
|
||||
--- 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)
|
||||
{
|
||||
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();
|
||||
|
|
Loading…
Add table
Reference in a new issue