Skip to content

Commit bdb25fb

Browse files
committed
Merge branch 'master' into fix-logging-crash
2 parents 3346bb6 + 842f73d commit bdb25fb

2 files changed

Lines changed: 191 additions & 46 deletions

File tree

.github/actions/spelling/allow.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,13 +221,15 @@ ipresolve
221221
isv
222222
itemdb
223223
itimerspec
224+
jobc
224225
journalctl
225226
jsvar
226227
kdbx
227228
kde
228229
keepass
229230
keyboxd
230231
keyutils
232+
kinfo
231233
kotlin
232234
Kql
233235
krb
@@ -335,6 +337,7 @@ newfile
335337
nexisting
336338
nfds
337339
nfor
340+
ngroups
338341
nintegrity
339342
niop
340343
noar
@@ -369,13 +372,15 @@ opensuse
369372
outp
370373
overallocated
371374
pacman
375+
paddr
372376
pamac
373377
parentid
374378
passoff
375379
pastebin
376380
permessage
377381
pfa
378382
PFN
383+
pgid
379384
pgrep
380385
phlibi
381386
phobos
@@ -432,6 +437,7 @@ restorecon
432437
retryable
433438
retu
434439
revents
440+
rgid
435441
rko
436442
rlc
437443
rlim
@@ -445,8 +451,10 @@ rpmuncompress
445451
Rproj
446452
rrodrigueznt
447453
rsnapshot
454+
rssize
448455
rsv
449456
rtud
457+
ruid
450458
rul
451459
ruleset
452460
runstatedir
@@ -460,6 +468,7 @@ scgi
460468
scl
461469
sdlang
462470
Searchmonkey
471+
segsz
463472
segv
464473
semanage
465474
sendfd
@@ -474,10 +483,15 @@ sharepoint
474483
shortnames
475484
sidx
476485
sigaction
486+
sigcatch
477487
sigchldhandler
478488
sigemptyset
489+
sigignore
490+
siglist
491+
sigmask
479492
signo
480493
sigpipe
494+
sigset
481495
skilion
482496
skinparam
483497
slist
@@ -493,9 +507,12 @@ statm
493507
stdc
494508
stringof
495509
Stringz
510+
structsize
496511
subobject
497512
subobjects
498513
svdir
514+
svgid
515+
svuid
499516
swapfile
500517
swapon
501518
swp
@@ -509,16 +526,21 @@ systemduserunitdir
509526
sysv
510527
tbh
511528
tdcockers
529+
tdev
512530
tempauth
513531
templ
514532
testbuild
533+
textvp
515534
Thh
516535
thnk
517536
tidx
518537
timerfd
519538
tkx
520539
tlsv
540+
tpgid
541+
tracep
521542
trashinfo
543+
tsid
522544
Tting
523545
tval
524546
typecons
@@ -540,9 +562,11 @@ userpass
540562
usl
541563
valgrind
542564
verifypeer
565+
vmspace
543566
vsid
544567
vti
545568
wal
569+
wchan
546570
Wds
547571
websockets
548572
webtemplate

src/util.d

Lines changed: 167 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,20 +1850,33 @@ void displayMemoryUsageDetails() {
18501850

18511851
// Query the actual Resident Set Size (RSS) for the PID
18521852
pid_t pid = getCurrentPID();
1853-
ulong currentRSS = getRSS(pid);
1854-
addLogEntry("current Resident Set Size (RSS) = " ~ to!string(currentRSS) ~ " KB");
1853+
ulong currentRSS;
1854+
version (FreeBSD) {
1855+
currentRSS = getRSSFreeBSD(pid);
1856+
} else version (linux) {
1857+
currentRSS = getRSSLinux(pid);
1858+
} else {
1859+
currentRSS = getRSS(pid);
1860+
}
18551861

1856-
// Calculate difference
1857-
if (previousRSS != 0) {
1858-
addLogEntry("previous Resident Set Size (RSS) = " ~ to!string(previousRSS) ~ " KB");
1859-
// Delta between current and previous RSS
1860-
long rssDifference = cast(long) currentRSS - cast(long) previousRSS;
1861-
string sign = rssDifference > 0 ? "+" : (rssDifference < 0 ? "" : "");
1862-
addLogEntry("difference in Resident Set Size (RSS) = " ~ sign ~ to!string(rssDifference) ~ " KB");
1862+
if (currentRSS != 0) {
1863+
addLogEntry("current Resident Set Size (RSS) = " ~ to!string(currentRSS) ~ " KB");
1864+
1865+
// Calculate difference
1866+
if (previousRSS != 0) {
1867+
addLogEntry("previous Resident Set Size (RSS) = " ~ to!string(previousRSS) ~ " KB");
1868+
// Delta between current and previous RSS
1869+
long rssDifference = cast(long) currentRSS - cast(long) previousRSS;
1870+
string sign = rssDifference > 0 ? "+" : (rssDifference < 0 ? "" : "");
1871+
addLogEntry("difference in Resident Set Size (RSS) = " ~ sign ~ to!string(rssDifference) ~ " KB");
1872+
}
1873+
1874+
// Update the previous RSS value only after a valid RSS sample
1875+
previousRSS = currentRSS;
1876+
} else {
1877+
addLogEntry("current Resident Set Size (RSS) = unavailable");
18631878
}
18641879

1865-
// Update the previous RSS value
1866-
previousRSS = currentRSS;
18671880
addLogEntry("-----------------------------------------------------");
18681881
addLogEntry();
18691882
}
@@ -2008,48 +2021,156 @@ void forceExit() {
20082021

20092022
// Get the current PID of the application
20102023
pid_t getCurrentPID() {
2011-
// The '/proc/self' is a symlink to the current process's proc directory
2012-
string path = "/proc/self/stat";
2013-
2014-
// Read the content of the stat file
2015-
string content;
2016-
try {
2017-
content = readText(path);
2018-
} catch (Exception e) {
2019-
writeln("Failed to read stat file: ", e.msg);
2020-
return 0;
2021-
}
2022-
2023-
// The first value in the stat file is the PID
2024-
auto parts = split(content);
2025-
return to!pid_t(parts[0]); // Convert the first part to pid_t
2024+
return getpid();
20262025
}
20272026

20282027
// Access the Resident Set Size (RSS) based on the PID of the running application
20292028
ulong getRSS(pid_t pid) {
2030-
// Construct the path to the statm file for the given PID
2031-
string path = format("/proc/%s/statm", to!string(pid));
2029+
version (FreeBSD) {
2030+
return getRSSFreeBSD(pid);
2031+
} else version (linux) {
2032+
return getRSSLinux(pid);
2033+
} else {
2034+
return 0;
2035+
}
2036+
}
20322037

2033-
// Read the content of the file
2034-
string content;
2035-
try {
2036-
content = readText(path);
2037-
} catch (Exception e) {
2038-
writeln("Failed to read statm file: ", e.msg);
2039-
return 0;
2040-
}
2038+
// Access the Resident Set Size (RSS) using the Linux /proc filesystem
2039+
ulong getRSSLinux(pid_t pid) {
2040+
if (pid <= 0) {
2041+
return 0;
2042+
}
2043+
2044+
// Construct the path to the statm file for the given PID
2045+
string path = format("/proc/%s/statm", to!string(pid));
20412046

2042-
// Split the content and get the RSS (second value)
2043-
auto stats = split(content);
2044-
if (stats.length < 2) {
2045-
writeln("Unexpected format in statm file.");
2046-
return 0;
2047-
}
2047+
// Read the content of the file
2048+
string content;
2049+
try {
2050+
content = readText(path);
2051+
} catch (Exception e) {
2052+
addLogEntry("Failed to read statm file: " ~ e.msg);
2053+
return 0;
2054+
}
20482055

2049-
// RSS is in pages, convert it to kilobytes
2050-
ulong rssPages = to!ulong(stats[1]);
2051-
ulong rssKilobytes = rssPages * sysconf(_SC_PAGESIZE) / 1024;
2052-
return rssKilobytes;
2056+
// Split the content and get the RSS (second value)
2057+
auto stats = split(content);
2058+
if (stats.length < 2) {
2059+
addLogEntry("Unexpected format in statm file: " ~ path);
2060+
return 0;
2061+
}
2062+
2063+
// RSS is in pages, convert it to kilobytes
2064+
ulong rssPages;
2065+
try {
2066+
rssPages = to!ulong(stats[1]);
2067+
} catch (Exception e) {
2068+
addLogEntry("Failed to parse RSS page count from statm file: " ~ path ~ " : " ~ e.msg);
2069+
return 0;
2070+
}
2071+
2072+
auto pageSize = sysconf(_SC_PAGESIZE);
2073+
if (pageSize <= 0) {
2074+
addLogEntry("Failed to determine system page size while calculating Linux RSS");
2075+
return 0;
2076+
}
2077+
2078+
ulong rssKilobytes = (rssPages * cast(ulong) pageSize) / 1024;
2079+
return rssKilobytes;
2080+
}
2081+
2082+
// Access the Resident Set Size (RSS) using FreeBSD-native process telemetry
2083+
ulong getRSSFreeBSD(pid_t pid) {
2084+
if (pid <= 0) {
2085+
return 0;
2086+
}
2087+
2088+
version (FreeBSD) {
2089+
import core.sys.freebsd.sys.sysctl : CTL_KERN, KERN_PROC, KERN_PROC_PID, sysctl;
2090+
import core.sys.freebsd.sys.types : segsz_t, vm_size_t;
2091+
import core.sys.posix.signal : sigset_t;
2092+
import core.sys.posix.sys.types : gid_t, uid_t;
2093+
2094+
// DRuntime does not expose sys/user.h as a portable kinfo_proc binding, so
2095+
// define only the stable kinfo_proc prefix required to reach ki_rssize.
2096+
// The full sysctl result is still queried into a correctly-sized byte buffer.
2097+
extern(C) struct FreeBSDKinfoProcRSSPrefix {
2098+
int ki_structsize;
2099+
int ki_layout;
2100+
void* ki_args;
2101+
void* ki_paddr;
2102+
void* ki_addr;
2103+
void* ki_tracep;
2104+
void* ki_textvp;
2105+
void* ki_fd;
2106+
void* ki_vmspace;
2107+
const(void)* ki_wchan;
2108+
pid_t ki_pid;
2109+
pid_t ki_ppid;
2110+
pid_t ki_pgid;
2111+
pid_t ki_tpgid;
2112+
pid_t ki_sid;
2113+
pid_t ki_tsid;
2114+
short ki_jobc;
2115+
short ki_spare_short1;
2116+
uint ki_tdev_freebsd11;
2117+
sigset_t ki_siglist;
2118+
sigset_t ki_sigmask;
2119+
sigset_t ki_sigignore;
2120+
sigset_t ki_sigcatch;
2121+
uid_t ki_uid;
2122+
uid_t ki_ruid;
2123+
uid_t ki_svuid;
2124+
gid_t ki_rgid;
2125+
gid_t ki_svgid;
2126+
short ki_ngroups;
2127+
short ki_spare_short2;
2128+
gid_t[16] ki_groups;
2129+
vm_size_t ki_size;
2130+
segsz_t ki_rssize;
2131+
}
2132+
2133+
int[4] mib = [
2134+
CTL_KERN,
2135+
KERN_PROC,
2136+
KERN_PROC_PID,
2137+
cast(int) pid
2138+
];
2139+
2140+
size_t processInfoLength;
2141+
if (sysctl(mib.ptr, cast(uint) mib.length, null, &processInfoLength, null, 0) != 0) {
2142+
addLogEntry("Failed to determine FreeBSD process RSS buffer size via sysctl for PID: " ~ to!string(pid));
2143+
return 0;
2144+
}
2145+
2146+
if (processInfoLength < FreeBSDKinfoProcRSSPrefix.sizeof) {
2147+
addLogEntry("Failed to query FreeBSD process RSS via sysctl: returned process information is too small for PID: " ~ to!string(pid));
2148+
return 0;
2149+
}
2150+
2151+
auto processInfo = new ubyte[](processInfoLength);
2152+
if (sysctl(mib.ptr, cast(uint) mib.length, processInfo.ptr, &processInfoLength, null, 0) != 0) {
2153+
addLogEntry("Failed to query FreeBSD process RSS via sysctl for PID: " ~ to!string(pid));
2154+
return 0;
2155+
}
2156+
2157+
if (processInfoLength < FreeBSDKinfoProcRSSPrefix.sizeof) {
2158+
addLogEntry("Failed to query FreeBSD process RSS via sysctl: incomplete process information returned for PID: " ~ to!string(pid));
2159+
return 0;
2160+
}
2161+
2162+
auto processInfoPrefix = cast(FreeBSDKinfoProcRSSPrefix*) processInfo.ptr;
2163+
auto pageSize = sysconf(_SC_PAGESIZE);
2164+
if (pageSize <= 0) {
2165+
addLogEntry("Failed to determine system page size while calculating FreeBSD RSS");
2166+
return 0;
2167+
}
2168+
2169+
// FreeBSD reports ki_rssize in pages.
2170+
return (cast(ulong) processInfoPrefix.ki_rssize * cast(ulong) pageSize) / 1024;
2171+
} else {
2172+
return 0;
2173+
}
20532174
}
20542175

20552176
// Getting around the @nogc problem

0 commit comments

Comments
 (0)