Hello, as the title says, I am trying to access Bluetooth in a system daemon. I am running on MacOS Sonoma 14.5.
When initializing Bluetooth, my daemon received Unauthorized state.
I have tried to add my daemon in the system settings (System Preferences > Security & Privacy > Privacy > Bluetooth) "Allow applications to access Bluetooth" by adding the program executable path defined by the entry Program of my system daemon as suggested here: https://developer.apple.com/forums/thread/662459.
But I am still having the issue.
Writing a system daemon with Bluetooth is not my final goal. The bigger picture is the smartcard reader driver with Bluetooth access which as the same issue and the solution is probably related.
I do not remember how but my smartcard reader driver use to work with Bluetooth but it does now with the same Unauthorized error.
As far as I can see daemon and smartcard drivers does not have support for entitlement.
Here are the logs for my sample system daemon:
my_daemon [0x6000011b0000] activating connection: mach=true listener=false peer=false name=com.apple.server.bluetooth.le.att.xpc
bluetoothd [0x7f804828e8a0] activating connection: mach=false listener=false peer=true name=com.apple.server.bluetooth.le.att.xpc.peer[76672].0x7f804828e8a0
bluetoothd Received XPC message "CBMsgIdCheckIn" from session ""
bluetoothd Received XPC check-in from session "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67" fAccessLevel 0 fProgrammaticPairing 0 fLimitedForMediaAccess 0
bluetoothd Access level is less than kXPCAccessLevelSystem for session "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67". Restricted state operation not allowed
bluetoothd Sending 'session attached' event for session "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67"
bluetoothd Attached session for "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67" with session: 0x7f804802d1b0, session handle: 0xef8d0000
bluetoothd Registering peripheral session "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67" with backgrounding: off, persistence: off (CBSR) restoreID: (null)
bluetoothd Error getting Application State for <private>: <private>, 3
bluetoothd Error getting Application State for <private>: <private>, 3
bluetoothd Session "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67" tccRequired : 1
bluetoothd ReadyForTCC. TCC required:1 fLimitedForMediaAccess:0 fDeviceAccessForMediaExtension:0
bluetoothd Session "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67" : needsRestrictedStateOperation = 0, overrideRestrictedState = 0 , denylistMode = 0, receivesControllerBTClockEvents=0
my_daemon Received CBMsgIdReadyForTCC
my_daemon Running performTccCheck CBManager tccAvail 1, tccRequired 1
my_daemon TCC required
my_daemon [0x6000011b8000] activating connection: mach=true listener=false peer=false name=com.apple.tccd
my_daemon [0x6000011b8000] failed to do a bootstrap look-up: xpc_error=[3: No such process]
my_daemon [0x6000011b8000] invalidated after a failed init
my_daemon send_message_with_reply(): user tccd unavailable, sending 0x600000ab4000 to system tccd
my_daemon [0x6000011b4000] activating connection: mach=true listener=false peer=false name=com.apple.tccd.system
tccd [0x7fd4d1f7ed80] activating connection: mach=false listener=false peer=true name=com.apple.tccd.system.peer[76672].0x7fd4d1f7ed80
tccd REQUEST: tccd_uid=0, sender_pid=76672, sender_uid=0, sender_auid=-1, function=TCCAccessRequest, msgID=76672.1
tccd AUTHREQ_CTX: msgID=76672.1, function=<private>, service=kTCCServiceBluetoothAlways, preflight=no, query=1, client_dict=(null), daemon_dict=<private>
tccd AUTHREQ_ATTRIBUTION: msgID=76672.1, attribution={requesting={TCCDProcess: identifier=my_daemon-5555494498236e3b5e2e395b93c13af176769937, pid=76672, auid=0, euid=0, binary_path=/Users/olivier/daemon/my_daemon}, },
tccd AUTHREQ_SUBJECT: msgID=76672.1, subject=/Users/olivier/daemon/my_daemon,
tccd Refusing TCCAccessRequest for service kTCCServiceBluetoothAlways from client Sub:{/Users/olivier/daemon/my_daemon}Resp:{TCCDProcess: identifier=my_daemon-5555494498236e3b5e2e395b93c13af176769937, pid=76672, auid=0, euid=0, binary_path=/Users/olivier/daemon/my_daemon} in background session
tccd AUTHREQ_RESULT: msgID=76672.1, authValue=0, authReason=5, authVersion=1, error=(null),
tccd REPLY: (0) function=TCCAccessRequest, msgID=76672.1
my_daemon [0x6000011b4000] invalidated after the last release of the connection object
bluetoothd Received XPC message "CBMsgIdTCCDone" from session "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67"
tccd [0x7fd4d1f7ed80] invalidated after getting a no-senders notification - client is gone
bluetoothd [0x7f80482820f0] activating connection: mach=true listener=false peer=false name=com.apple.tccd.system
tccd [0x7fd4d32585f0] activating connection: mach=false listener=false peer=true name=com.apple.tccd.system.peer[169].0x7fd4d32585f0
tccd REQUEST: tccd_uid=0, sender_pid=169, sender_uid=0, sender_auid=-1, function=TCCAccessRequest, msgID=169.48
tccd [0x7fd4d313d880] activating connection: mach=true listener=false peer=false name=com.apple.tccd
tccd [0x7fd4d313d880] failed to do a bootstrap look-up: xpc_error=[3: No such process]
bluetoothd [0x7f80482820f0] invalidated after the last release of the connection object
bluetoothd Bluetooth user permission alwaysAuth: denied
tccd [0x7fd4d313d880] invalidated after a failed init
tccd FORWARD: to=com.apple.tccd/0, request: {
require_purpose=<xpc_null>
service="kTCCServiceBluetoothAlways"
function="TCCAccessRequest"
preflight=true
target_token={pid:76672, auid:-1, euid:0}
TCCD_MSG_ID="169.48"
background_session=false
}
tccd REPLY: from=com.apple.tccd, reply: {
XPCErrorDescription="Connection invalid"
}
tccd forwardMessage error: Connection invalid.
tccd [0x7fd4d3152bf0] activating connection: mach=false listener=false peer=true name=com.apple.tccd.system.peer[169].0x7fd4d3152bf0
bluetoothd [0x7f80482820f0] activating connection: mach=true listener=false peer=false name=com.apple.tccd.system
tccd REQUEST: tccd_uid=0, sender_pid=169, sender_uid=0, sender_auid=-1, function=TCCAccessRequest, msgID=169.49
tccd [0x7fd4d32585f0] invalidated after getting a no-senders notification - client is gone
tccd [0x7fd4d1f4c810] activating connection: mach=true listener=false peer=false name=com.apple.tccd
tccd [0x7fd4d1f4c810] failed to do a bootstrap look-up: xpc_error=[3: No such process]
tccd [0x7fd4d1f4c810] invalidated after a failed init
tccd FORWARD: to=com.apple.tccd/0, request: {
require_purpose=<xpc_null>
service="kTCCServiceBluetoothAlways"
function="TCCAccessRequest"
preflight=true
target_token={pid:76672, auid:-1, euid:0}
TCCD_MSG_ID="169.49"
background_session=false
}
tccd REPLY: from=com.apple.tccd, reply: {
XPCErrorDescription="Connection invalid"
}
tccd forwardMessage error: Connection invalid.
Post
Replies
Boosts
Views
Activity
The context is to create a model instance in SwitfData and return it.
This model as a unique attribute (defined by @Attribute(.unique)). The application runs fine the first time but on the second run, it fails with EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP).
What the reason behind this crash?
Here is my sample application to duplicate the issue. The issue is reproducible on MacOS and iOS:
import SwiftUI
import SwiftData
@available(iOS 17, *)
@available(macOS 11, *)
@Model
public final class MyModel : CustomStringConvertible {
@Attribute(.unique) var uuid: UUID
init(uuid: UUID) throws {
self.uuid = uuid
}
public var description: String {
return self.uuid.uuidString
}
}
@available(iOS 17, *)
@available(macOS 11, *)
@ModelActor
public actor LocalDatabaseService {
public static let shared = LocalDatabaseService()
let schema = Schema([MyModel.self])
public init() {
self.modelContainer = try! ModelContainer(for: self.schema)
let context = ModelContext(modelContainer)
self.modelExecutor = DefaultSerialModelExecutor(modelContext: context)
}
public func createMyModel(uuid: UUID) throws -> MyModel {
let myModel = try MyModel(uuid: uuid)
let modelContext = self.modelContext
modelContext.insert(myModel)
try modelContext.save()
return myModel
}
}
struct ContentView: View {
var body: some View {
Task {
let id = UUID(uuidString: "9C66CA5B-D91C-480F-B02C-2D14EEB49902")!
let myModel = try await LocalDatabaseService.shared.createMyModel(uuid: id)
print("myModel:\(myModel)")
print("DONE")
}
return VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
}
.padding()
}
}
#Preview {
return ContentView()
}
Note: a workaround is to returned the fetched model instance return try self.getMyModel(uuid: uuid):
func getMyModel(uuid: UUID) throws -> MyModel {
let fetchDescriptor = FetchDescriptor<MyModel>(predicate: #Predicate { $0.uuid == uuid })
let serverList = try modelContext.fetch(fetchDescriptor)
if !serverList.isEmpty {
if let first = serverList.first {
return first
}
}
fatalError("Could not find MyModel with uuid \(uuid)")
}
... but it does not explain the crash.
Here is my current code:
@Model
final public class ServerModel {
@Attribute(.unique) var serverUrl: URL
init(serverUrl: URL) {
self.serverUrl = serverUrl
}
}
@ModelActor
public actor MyDatabaseService {
public static var shared = MyDatabaseService()
public init() {
self.modelContainer = try! ModelContainer(for: ServerModel.self)
let context = ModelContext(modelContainer)
self.modelExecutor = DefaultSerialModelExecutor(modelContext: context)
}
public func listServers() throws -> [ServerModel] {
let descriptor = FetchDescriptor<ServerModel>()
return try modelContext.fetch(descriptor)
}
}
When try to call try await MyDatabaseService.shared.listServers()
There are two problems:
ServerModel is not Sendable
"Reference to static property 'shared' is not concurrency-safe because it involves shared mutable state; this is an error in Swift 6"
For the first one, I can solve it by doing:
public struct Server {
let serverUrl: URL;
}
@Model
final public class ServerModel {
@Attribute(.unique) var serverUrl: URL
init(serverUrl: URL) {
self.serverUrl = serverUrl
}
func getSendable() -> Server {
return Server(serverUrl: self.serverUrl)
}
}
@ModelActor
public actor MyDatabaseService {
(...)
public func listServers() throws -> [Server] {
let descriptor = FetchDescriptor<ServerModel>()
return try modelContext.fetch(descriptor).map { $0.getSendable() }
}
}
I am wondering if there is a smarter solution to this first issue. SwiftData already require to define the model with basic/codable types, so if there was a magic way to get a sendable from the model.
I try to make my model 'Codable' but 'Codable' is not compatible with 'Sendable'.
For my second issue, the singleton issue. I do not really know how to fix it.
Here is my models:
import SwiftData
@Model
final public class FirstModel {
let name: String
@Relationship(deleteRule: .cascade, inverse: \SecondModel.parent) var children = [SecondModel]()
init(name: String) {
self.name = name
}
}
@Model
final public class SecondModel {
let parent: FirstModel
let name: String
@Relationship(deleteRule: .cascade, inverse: \ThirdModel.parent) var children = [ThirdModel]()
init(name: String, parent: FirstModel) {
self.name = name
self.parent = parent
}
}
@Model
final public class ThirdModel {
let parent: SecondModel
let name: String
init(name: String, parent: SecondModel) {
self.name = name
self.parent = parent
}
}
Then I create my model entries:
let schema = Schema([
FirstModel.self,
SecondModel.self,
ThirdModel.self
])
let container = try ModelContainer(for: schema)
let context = ModelContext(container)
let firstModel = FirstModel(name: "my first model")
let secondModel = SecondModel(name: "my second model", parent: firstModel)
let thirdModel = ThirdModel(name: "my third model", parent: secondModel)
context.insert(firstModel)
context.insert(secondModel)
context.insert(thirdModel)
try context.save()
I want to retrieve the children from my models:
print("-- Fetch Third Model")
let thirdFetchDescriptor: FetchDescriptor<ThirdModel> = FetchDescriptor<ThirdModel>(predicate: #Predicate { $0.name == "my third model" })
let thirdModels = try context.fetch(thirdFetchDescriptor)
for entry in thirdModels {
print(">>> \(entry) - \(entry.parent) - \(entry.parent.parent)")
}
print("-- Fetch First Model")
let firstFetchDescriptor: FetchDescriptor<FirstModel> = FetchDescriptor<FirstModel>(predicate: #Predicate { $0.name == "my first model" })
let firstModels = try context.fetch(firstFetchDescriptor)
for entry in firstModels {
print(">>> \(entry) - \(entry.children)")
for child in entry.children {
print("\t>>> \(child) - \(child.children)")
}
}
... But it does not seem to work:
-- Fetch Third Model
>>> cardapart_sdk_app_ui.ThirdModel - cardapart_sdk_app_ui.SecondModel - cardapart_sdk_app_ui.FirstModel
-- Fetch First Model
>>> cardapart_sdk_app_ui.FirstModel - []
What I would expect to see:
-- Fetch First Model
>>> cardapart_sdk_app_ui.FirstModel - [cardapart_sdk_app_ui.SecondModel]
>>> cardapart_sdk_app_ui.SecondModel - [cardapart_sdk_app_ui.ThirdModel]
I am not sure what I am doing wrong or missing...
I am writing a SPM based project for MacOS. In this project? I need to access MacOS Keychain.
I am write a swift test built by SPM testTarget(). I can see it generates a bundle ./.build/x86_64-apple-macosx/debug/MyProjectTests.xctest with an executable:
% file ./.build/x86_64-apple-macosx/debug/MyProjectPackageTests.xctest/Contents/MacOS/MyProjectPackageTests
./.build/x86_64-apple-macosx/debug/MyProjectPackageTests.xctest/Contents/MacOS/MyProjectPackageTests: Mach-O 64-bit bundle x86_64
This bundle file cannot be executed. How can I execute its tests?
I tried with xcodebuild test-without-building -xctestrun ./.build/x86_64-apple-macosx/debug/MyProjectPackageTests.xctest -destination 'platform=macOS' without any chance.
Obviously the next question is can I 'simply' add entitlement to this bundle with codesign to fix my enttilement error.
My error when running the test is A required entitlement isn't present.
Context: I am trying to create a XCFramework that I can reuse it in my Swift app. My example is based on SPM (Swift Package Manager) but I had the same import error no such module when I tried to import my XCFramework in XCode.
Here is the code for XCFramework:
Package.swift
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MySDK",
platforms: [.macOS(.v14), .iOS(.v13), .watchOS(.v6)],
products: [
.library(name: "MySDK", type: .dynamic, targets: ["MySDK"]),
],
targets: [
.target(name: "MySDK")
]
)
Sources/MySDK/my_sdk.swift
public func myHelloStr() -> String {
return "Bonjour le monde!"
}
To generate the XCFramework:
$ xcodebuild build -scheme MySDK -destination "platform=macOS" -derivedDataPath DerivedData SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES
$ xcodebuild -create-xcframework -framework DerivedData/Build/Products/Debug/PackageFrameworks/MySDK.framework -output MyFramework.xcframework
I can see MyFramework.xcframework folder with
- `Info.plist`
- `macos-x86_64/MySDK.framework/MySDK`
- `macos-x86_64/MySDK.framework/Resources/Info.plist`
- `macos-x86_64/MySDK.framework/Versions/A/MySDK`
- `macos-x86_64/MySDK.framework/Versions/A/Resources/Info.plist`
- `macos-x86_64/MySDK.framework/Versions/Current/MySDK`
- `macos-x86_64/MySDK.framework/Versions/Current/Resources/Info.plist`
Then I create a new SPM project MyApp
with Package.swift
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "TestApp",
platforms: [.macOS(.v14), .iOS(.v13), .watchOS(.v6)],
products: [
.executable(name: "MyApp", targets: ["MyApp"])
],
targets: [
.executableTarget(name: "MyApp",
dependencies: [
.target(name: "MyFramework")
]
),
.binaryTarget(
name: "MyFramework",
path: "../test_sdk/MyFramework.xcframework"
)
]
)
And Sources/MyApp/main.swift:
import MySDK
print("Hello World: \(myHelloStr())")
$ swift run
Building for debugging...
error: emit-module command failed with exit code 1 (use -v to see invocation)
/Users/olivier/dev/test_app/Sources/MyApp/main.swift:1:8: error: no such module 'MySDK'
import MySDK
^
/Users/olivier/dev/test_app/Sources/MyApp/main.swift:1:8: error: no such module 'MySDK'
import MySDK
^
error: fatalError
If I generate my XCFramework using xcodebuild archive instead of xcodebuild build such as described in this doc https://developer.apple.com/documentation/xcode/creating-a-multi-platform-binary-framework-bundle:
$ xcodebuild archive -scheme MySDK -destination "platform=macOS" -derivedDataPath DerivedData -archivePath "archives/MyFramework" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES
(...)
** ARCHIVE SUCCEEDED **
$ xcodebuild -create-xcframework -archive archives/MyFramework.xcarchive -framework MySDK.framework -output MyFramework.xcframework
error: the path does not point to a valid framework: /Users/olivier/dev/test_sdk/archives/MyFramework.xcarchive/Products/Library/Frameworks/MySDK.framework
... it's not normal because I have these paths in /Users/olivier/dev/test_sdk/archives/MyFramework.xcarchive/Products:
/Users/olivier/dev/test_sdk/archives/MyFramework.xcarchive/Products/Users/olivier/Objects/MySDK.o
/Users/olivier/dev/test_sdk/archives/MyFramework.xcarchive/Products/usr/local/lib/MySDK.framework/...
XCode version
$ xcodebuild -version
Xcode 15.2
Build version 15C500b