ohmu
·
2026-10-15
1#include "processes.h"
2#include "common/debug.h"
3#include "common/mallocHelper.h"
4
5#include <errno.h>
6#include <string.h>
7
8#include <sys/sysctl.h>
9#import <libproc.h>
10
11const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) {
12 int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
13 size_t length;
14
15 if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) {
16 FF_DEBUG("sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, nullptr}) failed: %s", strerror(errno));
17 return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, nullptr}) failed";
18 }
19
20 // The process table may change between the two sysctl calls; retry with a larger buffer.
21 length += length / 8 + sizeof(struct kinfo_proc);
22 FF_AUTO_FREE struct kinfo_proc* processes = malloc(length);
23
24 if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) {
25 FF_DEBUG("sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, processes}) failed: %s", strerror(errno));
26 return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, processes}) failed";
27 }
28
29 uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc));
30
31 for (uint32_t i = 0; i < count; ++i) {
32 const struct kinfo_proc* proc = &processes[i];
33 if (!options->countKprocs && (proc->kp_proc.p_flag & P_SYSTEM)) {
34 continue;
35 }
36 result->processes++;
37
38 pid_t pid = proc->kp_proc.p_pid;
39 struct proc_taskinfo taskInfo;
40 if (proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &taskInfo, sizeof(taskInfo)) == sizeof(taskInfo)) {
41 // NOTE: This fails for system processes
42 result->threads += (uint32_t) taskInfo.pti_threadnum;
43 }
44 }
45
46 return nullptr;
47}