looks like it uses either C++ or Objective-C exception mechanism.
That’s not an exception. Rather, this is error handling code that just happens to log a backtrace.
Do I somehow opt-out of using sockets or should they be not
used by default?
Network framework uses user-space networking by default but there are lots of constraints involved. Consider this test project:
import Foundation
import Network
func start() -> NWConnection {
print("connection will start")
let connection = NWConnection(to: .hostPort(host: "example.com", port: 80), using: .tcp)
connection.stateUpdateHandler = { newState in
print("connection did change state, new: \(newState)")
}
connection.start(queue: .main)
return connection
}
func main() throws {
let connections = (0..<10).map { _ in start() }
withExtendedLifetime(connections) {
print("did start connections, pid: \(getpid())")
dispatchMain()
}
}
try main()
Running it on macOS 14.4.1, this is what I see:
% ./Test751581
connection will start
…
connection will start
did start connections, pid: 84766
connection did change state, new: preparing
…
connection did change state, new: preparing
connection did change state, new: ready
…
connection did change state, new: ready
Now let’s look at the process’s file descriptors:
% lsof -p 84766
COMMAND … USER FD TYPE DEVICE SIZE/OFF NODE NAME
Test751581 … quinn cwd DIR 1,15 192 27676134 /Users/quinn/…
Test751581 … quinn txt REG 1,15 161760 29137837 /Users/quinn/…
Test751581 … quinn txt REG 1,15 58072 29015793 /Library/…
Test751581 … quinn 0u CHR 16,1 0t5163 3215 /dev/ttys001
Test751581 … quinn 1u CHR 16,1 0t5163 3215 /dev/ttys001
Test751581 … quinn 2u CHR 16,1 0t5163 3215 /dev/ttys001
Test751581 … quinn 3 NPOLICY
Test751581 … quinn 4 CHAN flowsw E2F7D96B-046F-…
There are not 10 TCP sockets there. There is a flowsw
(flow switch) entry, which suggests user-space networking is in play.
Deploying skywalkctl
, I see the 10 connections:
% sudo skywalkctl flow -n -P 84766
Proto Local Address Remote Address …
tcp4 192.168.1.171.51497 93.184.215.14.80 …
tcp4 192.168.1.171.51496 93.184.215.14.80 …
tcp4 192.168.1.171.51489 93.184.215.14.80 …
tcp4 192.168.1.171.51498 93.184.215.14.80 …
tcp4 192.168.1.171.51490 93.184.215.14.80 …
tcp4 192.168.1.171.51494 93.184.215.14.80 …
tcp4 192.168.1.171.51495 93.184.215.14.80 …
tcp4 192.168.1.171.51491 93.184.215.14.80 …
tcp4 192.168.1.171.51493 93.184.215.14.80 …
tcp4 192.168.1.171.51492 93.184.215.14.80 …
Note that I had to disable iCloud Private Relay to get these results. Without that I see just a single user-space networking flow, the UDP (QUIC IIUC) flow to the private relay server.
Additionally, there are things that opt you out of user-space networking entirely. I don’t have a definitive list, but the most obvious candidate is legacy VPNs. If you can’t reproduce my results:
-
Retry on macOS 14.
-
Set up a vanilla VM and retry there.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"