#define
22 posts · Last used 22d
END OF TRANSMISSION. Thanks for riding along on this adventure. Remember to smash that subscribe and like button.. oh wait. Sorry. I'm on twitch.tv/cryosama sometimes fighting death on World of Warcraft Classic Hardcore, or coding (currently TapNet3D for various platforms).
This is what happens when computers/AI overlords piss me off, I fall down a hyperfocused rabbit-hole. I'll collect more information tomorrow and any that are submitted to me by other mac users who want to test and push your system to repro this. Then I'll file a bug report:
Title
macOS 26.6.2: Application Firewall causes CFIL/SOFLOW flow-state accumulation and periodic kernel network stalls
Product / Build
- macOS Tahoe 26.6.2
- Build 25G83
- Darwin 25.6.0
- XNU
12377.161.14~5 - Apple Silicon: M4 Pro Mac mini
Summary
With the macOS Application Firewall enabled, net.cfil.sock_attached_count and net.soflow.count rapidly accumulate from near zero to tens of thousands of live flow-state objects. Under sustained normal application/network activity, the population rises to roughly 75,000–80,000 entries and then oscillates around that high-water range.
At these elevated flow counts, the system develops recurring latency spikes affecting otherwise local low-latency traffic. ICMP to the directly connected default gateway normally completes in under 1 ms, but periodically stalls for 100–900+ ms.
Simultaneous packet capture shows the packets are present on the interface immediately while userspace delivery is delayed. This localizes the delay to the kernel networking path after BPF observation and before userspace receives the packet.
Kernel stackshots from the affected system show contention involving SOFLOW garbage collection, dlil_input_en0, socket receive paths, and the global CFIL read/write lock.
Observed behavior
After boot or after resetting firewall state, the system initially behaves normally.
With Application Firewall enabled:
07:14:12 SOFLOW=187 CFIL=152
09:51:10 SOFLOW=64840 CFIL=64591
18:44:57 SOFLOW=79508 CFIL=79270
The counters are not cumulative event counters. XNU source shows:
cfil_sock_attached_count++;
...
cfil_sock_attached_count--;
and:
soflow_attached_count++;
...
soflow_attached_count--;
so these values represent current retained/attached flow-state population.
The population eventually reaches a dynamic equilibrium near 75k–80k rather than returning toward the number of active userland sockets.
The machine typically has only hundreds of live Internet sockets at the same time.
Latency symptom
Under the affected state, ping to the directly connected gateway shows stalls such as:
0.5 ms
0.6 ms
444 ms
0.7 ms
...
713 ms
215 ms
0.6 ms
...
920 ms
416 ms
0.5 ms
Simultaneous tcpdump shows request and reply packets on en0 with sub-millisecond wire timing while ping(8) reports hundreds of milliseconds.
The observed sequence is therefore:
packet reaches en0
BPF/tcpdump observes packet
kernel delivery is delayed
userspace ping receives packet later
Kernel evidence
Symbolicated stackshots using the matching 26.6.2 KDK show the affected paths entering CFIL locking.
Representative paths include:
sosend
-> cfil_sock_udp_handle_data
-> cfil_sock_udp_get_info
-> cfil_rw_lock_shared
-> IORWLockRead
and input-side paths involving:
dlil_input_en0
-> proto_input
-> sbappendaddr
-> cfil_sock_udp_handle_data
-> cfil_info_alloc
-> cfil_rw_lock_exclusive
SOFLOW GC is also observed in:
soflow_gc_expire
-> cfil_dgram_gc_perform
-> cfil_sock_udp_unlink_flow
-> cfil_rw_lock_exclusive
and:
cfil_info_free
-> cfil_rw_lock_exclusive
Blocked readers are frequently owned by either:
dlil_input_en0
SOFLOW_GC
XNU source documents that the CFIL subsystem is protected by the global cfil_lck_rw.
GC behavior
Public XNU source defines:
#define SOFLOW_GC_IDLE_TO 30
#define SOFLOW_GC_MAX_COUNT 100
#define SOFLOW_GC_RUN_INTERVAL_NSEC (10 * NSEC_PER_SEC)
Observed runtime behavior matches periodic reclamation, but reclamation does not reduce the population back to a small working set. Instead, flow-state accumulates rapidly and later churns around a high equilibrium.
Application Firewall correlation
socketfilterfw is connected to:
com.apple.content-filter
and:
net.cfil.active_count = 1
while Application Firewall is enabled.
When the firewall is disabled:
net.cfil.active_count = 0
new CFIL population growth stops, while existing CFIL state is gradually reclaimed.
When the firewall is enabled again, new CFIL attachments resume.
This A/B behavior is reproducible.
Expected behavior
CFIL/SOFLOW state associated with expired or closed flows should be reclaimed promptly enough that the retained population remains proportional to active socket/flow usage.
Periodic garbage collection should not cause multi-hundred-millisecond stalls in unrelated packet delivery.
Actual behavior
CFIL/SOFLOW state grows into the tens of thousands despite only hundreds of live userland sockets.
At high population, recurring SOFLOW/CFIL cleanup produces contention on the global CFIL lock and coincides with severe local packet-delivery latency.
Impact
This is most visible in latency-sensitive workloads:
- video conferencing
- real-time audio
- streaming
- games
- SSH / remote shells
- interactive network applications
Bulk transfers and background tasks are less visibly affected because buffering masks short stalls.
Reproduction
- Boot macOS 26.6.2.
- Ensure Application Firewall is enabled.
- Run normal network-intensive applications for several hours.
- Periodically record:
sysctl -n net.soflow.count
sysctl -n net.cfil.sock_attached_count
sysctl -n net.cfil.active_count
- Observe CFIL/SOFLOW population increasing into tens of thousands.
- Run a high-frequency ping to the local gateway.
- Observe periodic 100–900+ ms latency excursions.
- Capture simultaneously with
tcpdump. - Observe that packets appear on
en0promptly while userspace ping delivery is delayed. - Disable Application Firewall and observe that new CFIL attachment growth stops.
Attachments I would include
- full CFIL/SOFLOW counter log
- graph showing growth from ~0 to ~80k
- ping log showing latency spikes
- simultaneous
tcpdumpcapture - bad-state spindump
- healthy-state spindump
- symbolicated kernel stack output from the matching KDK
systemextensionsctl listnetstat -anv -f systemlsofshowingsocketfilterfwconnected tocom.apple.content-filter- exact
sysctlsnapshots before/after firewall disable
Suggested engineering summary
Suspected CFIL/SOFLOW flow-lifetime or reclamation defect associated with Application Firewall. Flow-state population grows to ~80k, substantially exceeding live userland socket count. SOFLOW GC and CFIL teardown take the global
cfil_lck_rwexclusively, while packet delivery paths require the same lock shared. At elevated flow-state population, periodic GC/teardown correlates with 100–900+ ms local packet-delivery stalls. Disabling Application Firewall stops new CFIL attachment growth and allows the existing population to drain.
@thephd@pony.social if you allowed “auto x” for a default case, #define bar(X) _Generic(X, auto x: …) could become the least bad way to bind the expansion of a preprocessor macro to a variable inside a single expression
@fugueish@wandering.shop hmm yeah looks like clang hasn't gotten the memo yet. i can get this to work with gcc, but the standard doesn't allow type definitions in "underspecified" auto declarations, so i had to write
#define $Option(T) struct Option##T { T value; bool valid; }
#define $Some(T, v) ($Option(T)){ .value = v, .valid = true }
void printOption($Option(int) x) { ... }
int main() {
// can't use auto
$Option(int) o = $Some(int, 42);
printOption(o);
}