Why doesn't this work? (Specifically, it crashes.)
struct Item: Identifiable, Hashable, Codable {
var id = UUID()
var name: String? = nil
}
private let defaults: [Item] = [
Item(name: "Bread"),
Item(),
Item(name: "Peanut Butter"),
Item(name: "Jelly")
]
struct ContentView: View {
@State var selectedItem = Set<Item>()
@State var showSheet = false
var body: some View {
VStack {
ForEach(defaults, id: \.self) { item in
Button(item.name ?? "<unnamed>") {
self.selectedItem.removeAll()
self.selectedItem.insert(item)
print("Selected item is now \(self.selectedItem)")
self.showSheet = true
}
}
}
.sheet(isPresented: self.$showSheet) {
let _ = print("selected item \(self.selectedItem)")
RenameSheet(name: self.selectedItem.first!.name ?? "<no name>") {
self.selectedItem.removeAll()
}
}
.padding()
}
}
Based on the output from the prints, it gets set when the button is clicked, but is then empty when the sheet is presented.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
If there's another version of our app on the volume, it'll relocate the installed one there. This is particularly delightful, since nothing will work if it's not in /Applications.
We use pkgbuild and productbuild to create the .pkg file.
The code I have is
if (filterManager.providerConfiguration == nil)
{
NEFilterProviderConfiguration *providerConfiguration = [[NEFilterProviderConfiguration alloc] init];
providerConfiguration.filterPackets = YES;
providerConfiguration.filterPacketProviderBundleIdentifier = filterBundle.bundleIdentifier;
filterManager.providerConfiguration = providerConfiguration;
NSString *appName = [NSBundle mainBundle].infoDictionary[@"CFBundleName"];
if (appName != nil)
{
filterManager.localizedDescription = [NSString stringWithFormat:@"%@ (packet filter)", appName];
}
}
if (filterManager.enabled)
{
NSLog(@"Packet filter already enabled, not doing so again");
return;
}
filterManager.enabled = YES;
It's claiming the filter is already enabled. But System Settings > Network shows it there, with a yellow dot. My best guess is that it's showing up as already enabled in the preferences, even though it... isn't? I also log a message in the filter's init, and I don't see that showing up.
I've got sysdiagnose from it and a working system, and I'm going over soooooooo many log lines. I don't know what might be causing this, however.
I have this code in a network extension:
private func pathForToken(token: audit_token_t) -> String? {
var tokenCopy = token
let bufferSize = UInt32(4096)
let bytes = UnsafeMutablePointer<UInt8>.allocate(capacity: Int(bufferSize))
let length = proc_pidpath_audittoken(&tokenCopy, bytes, bufferSize)
if length != 0 {
return String(cString: bytes).lowercased()
}
return nil
}
bytes appears to be leaked -- the call stack is pathForToken(token:) to specialized static UnsafeMutablePointer.allocate(capacity:)
Do I need to do something to ensure bytes is released, since it doesn't seem to be happening on its own?
We're using this (on a mac) to do 3rd party authentication. The completion handler is getting
Authentication session got error: [The operation couldn’t be completed. (com.apple.AuthenticationServices.WebAuthenticationSession error 1.)], in domain: [com.apple.AuthenticationServices.WebAuthenticationSession]
That seems to be generated if the auth window is closed. However... it's not being closed, so we end up spawning a second one to do it, and this one seems to work.
Since we've had a lot of problems with XPC (bad design on my part, I'm sure), I tried changing the data communications between the TPP and the userland proxy to use sockets -- in this case (I've so many, many cases), I am trying to do an http proxy (so the TPP connects to, say, port 12345, sends
CONNECT ${host}:${port} HTTP/1.0
X-Proxy-Host: ${host}:${port}
It then reads a response, looking for a 200.
So that part works -- once I added the networking client entitlement, I could connect and write that and read the response. Now we are cooking with gas, right?
The application doing the connection (eg, curl) then sends the normal HTTP request, the TPP gets it, it writes it to the socket it created, the write succeeds (that is, returns the number of bytes in the request), and...
it doesn't show up on the interface. (Using tcpdump -i lo0 -s 0 -vvvvvvvvvvvvvvvvvvv -A port 12345.) Since it doesn't show up on the interface, the user-land proxy doesn't get it, and things are very confused for everyone.
If the connect() failed, I'd say, ah yes, sandboxed to heck and back, even with the entitlement can't do it. Or if the first write() or read() failed. But they don't fail, and the first round works. If the second write() failed, I could see that.
But it both succeeds and doesn't succeed, and quantum confuses the heck out of me.
I was trying to check the documentation for handleNewUDPFlow over at https://developer.apple.com/documentation/networkextension/neappproxyprovider/3192017-handlenewudpflow and... it says it's deprecated on everything. Retroactively.
I have
var idleScanTimer = DispatchSource.makeTimerSource()
as a class ivar. When the object is started, I have
self.idleScanTimer.schedule(deadline: .now(), repeating: Double(5.0*60))
(and it sets an event handler, that checks some times.)
When the object is stopped, it calls self.idleScanTimer.cancel().
At some point, the object containing it is deallocated, and ... sometimes, I think, not always, it crashes:
Crashed Thread: 61 Dispatch queue: NEFlow queue
[...]
Application Specific Information:
BUG IN CLIENT OF LIBDISPATCH: Release of an inactive object
[...]
Thread 61 Crashed:: Dispatch queue: NEFlow queue
0 libdispatch.dylib 0x7ff81c1232cd _dispatch_queue_xref_dispose.cold.2 + 24
1 libdispatch.dylib 0x7ff81c0f84f6 _dispatch_queue_xref_dispose + 55
2 libdispatch.dylib 0x7ff81c0f2dec -[OS_dispatch_source _xref_dispose] + 17
3 com.kithrup.simpleprovider 0x101df5fa7 MyClass.deinit + 87
4 com.kithrup.simpleprovider 0x101dfbdbb MyClass.__deallocating_deinit + 11
5 libswiftCore.dylib 0x7ff829a63460 _swift_release_dealloc + 16
6 com.kithrup.simpleprovider 0x101e122f4 0x101de7000 + 176884
7 libswiftCore.dylib 0x7ff829a63460 _swift_release_dealloc + 16
8 libsystem_blocks.dylib 0x7ff81bfdc654 _Block_release + 130
9 libsystem_blocks.dylib 0x7ff81bfdc654 _Block_release + 130
10 libdispatch.dylib 0x7ff81c0f3317 _dispatch_client_callout + 8
11 libdispatch.dylib 0x7ff81c0f9317 _dispatch_lane_serial_drain + 672
12 libdispatch.dylib 0x7ff81c0f9dfd _dispatch_lane_invoke + 366
13 libdispatch.dylib 0x7ff81c103eee _dispatch_workloop_worker_thread + 753
14 libsystem_pthread.dylib 0x7ff81c2a7fd0 _pthread_wqthread + 326
15 libsystem_pthread.dylib 0x7ff81c2a6f57 start_wqthread + 15
I tried changing it to an optional and having the deinit call .cancel() and set it to nil, but it still crashes.
I can't figure out how to get it deallocated in a small, standalone test program.
That's pretty much it -- I can increase memory, file descriptor, etc., but can I increase the number of threads?
(I've got a case where, in an error condition, my threads block [still trying to figure out why] and new ones are still being generated, until I hit a limit of 512 threads.)
Topic:
App & System Services
SubTopic:
Core OS
That's probably a bad title, let's try with specifics: we have a network extension, it has some classes / functions of its own, and they, when push comes to build, depend on (for example) NEAppProxyFlow and its subclasses. The code is written in Swift, since it is the language of the future.
If I want to do a unit test for my code, I need to provide something that at least looks like NEAppProxyFlow, since I can't otherwise create one. I thought I could provide my own NetworkExtension module for test case, but that... did not work well, and I still don't understand why.
On the other hand, I'm really bad at making unit tests, so the odds that I'm missing something fairly obvious to most other people are pretty high.
I have this in my start code:
for p in [4500] + Array(3478...3497) + Array(16384...16387) + Array(16393...16402) {
// According to the documentation, I *should* be able to
// use "" for the hostname, and prefix:0, but it complained
// about the prefix length, so we use the top bit for ipv4
// and ipv6.
let port = "\(p)"
os_log(.debug, log: Self.log, "Setting up to exclude port %{public}s", port)
let host_1 = NWHostEndpoint(hostname:"0.0.0.0", port: port)
let host_2 = NWHostEndpoint(hostname:"255.0.0.0", port: port)
let host_3 = NWHostEndpoint(hostname:"0::0", port: port)
let host_4 = NWHostEndpoint(hostname:"ffff::0", port: port)
for host in [host_1, host_3] {
let udpPortRule = NENetworkRule(destinationNetwork: host, prefix:1, protocol: .UDP)
excludeRules.append(udpPortRule)
}
}
settings.excludedNetworkRules = excludeRules
This produces the log message
2024-07-23 11:16:38.335649+0100 0x901984 Debug 0x0 20686 0 com.kithrup.SimpleTPP.Provider: [com.kithrup:Provider] Setting up to exclude port 3483
Later on, when running, I log the new flows in handleNewUDPFlow(:,initialRemoteEndpoint:), and it produces
2024-07-23 11:17:05.712055+0100 0x901984 Debug 0x0 20686 0 com.kithrup.SimpleTPP.Provider: [com.kithrup:Provider] handleNewUDPFlow(_:initialRemoteEndpoint:): new UDP flow for host 17.252.13.7:3483 app com.apple.identityservicesd
So port 3483 is definitely in the excludedRules array, but it's not being excluded.
(All of this is because I still can't figure out why FaceTime isn't working with us.)
BUG IN CLIENT OF LIBDISPATCH: Unexpected EV_VANISHED (do not destroy random mach ports or file descriptors)
Which, ok, clear: somehow a file descriptor is being closed before DispatchIO.close() is called, yes?
Only I can't figure out where it is being closed. I am currently using change_fdguard_np() to prevent closes anywhere else, and every single place where I call Darwin.close() is preceded by another call to change_fdguard_npand thenDispatchIO.close()`. eg
self.unguardSocket()
self.readDispatcher?.close()
Darwin.close(self.socket)
self.socket = -1
self.completion(self)
Using our transparent proxy provider, I noticed that the mbuf usage was... weird:
15839/750028 mbufs in use:
15810 mbufs allocated to data
29 mbufs allocated to packet headers
734189 mbufs allocated to caches
The amount allocated to caches does go down a bit, but nothing significantly. I started looking into this because I've had a couple of panics from remoted not checking in enough, and it was (as I recall, I can't find the crash logs now) mbuf-related.
I've looked through an older version of the xnu source, and nothing jumped out, but that doesn't have the code for the network extension support.
I hate mbufs and always have.
The archive build part works, and uses the correct entitlements file:
[Key] com.apple.developer.networking.networkextension
[Value]
[Array]
[String] app-proxy-provider-systemextension
That's from codesign -dv --entitlements - ...../NetworkExtensionExperiment.app
However, the distribution log shows
"Error Domain=DVTPortalProfileErrorDomain Code=4 \"Cannot create a Developer ID provisioning profile for \"com.kithrup.NetworkExtensionExperiment\".\" UserInfo={NSLocalizedDescription=Cannot create a Developer ID provisioning profile for \"com.kithrup.NetworkExtensionExperiment\"., IDEDistributionIssueSeverity=3, NSLocalizedRecoverySuggestion=The Network Extensions capability is not available for Developer ID provisioning profiles. Disable this feature and try again., NSUnderlyingError=0x600013e719b0 {Error Domain=DVTPortalProfileTypeErrorDomain Code=0 \"Cannot create a Developer ID provisioning profile.\" UserInfo={UnsupportedFeatureNames=(\n \"Network Extensions\"\n), NSLocalizedDescription=Cannot create a Developer ID provisioning profile., NSLocalizedRecoverySuggestion=The Network Extensions capability is not available for Developer ID provisioning profiles. Disable this feature and try again.}}}",
"Error Domain=IDEProfileLocatorErrorDomain Code=1 \"No profiles for 'com.kithrup.NetworkExtensionExperiment' were found\" UserInfo={IDEDistributionIssueSeverity=3, NSLocalizedDescription=No profiles for 'com.kithrup.NetworkExtensionExperiment' were found, NSLocalizedRecoverySuggestion=Xcode couldn't find any Developer ID provisioning profiles matching 'com.kithrup.NetworkExtensionExperiment'.}"
which, given that I was able to build a signed version with the entitlement as shown first, seems to be a problem.
All my years of hating xcode are coming back to haunt me, I can tell.
I create a DispatchIO object (in Swift) from a socketpair, set the low/high water marks to 1, and then call read on it. Elsewhere (multi-threaded, of course), I get data from somewhere, and write to the other side of it. Then when my data is done, I call dio?.close()
The cleanup handler never gets called.
What am I missing? (ETA: Ok, I can get it to work by calling dio?.close(flags: .stop) so that may be what I was missing.)
(Also, I really wish it would get all the data available at once for the read, rather than 1 at a time.)