Comments (13)
Tomorrow I'll begin porting this into my app; it may take me some time as I have some handlers which leverage Swift's async so I'll need to change what I'm doing there.
Great to hear it's working for you.
The branch I pointed you at was a proof of concept, it's possible the exact API which I release won't match - but it will enable the same concurrent behavior you're currently getting. At most you'd need to set one or two additional properties (if they're not the default ones) for the server.
There's a good chance I'm going to enable both unrestricted concurrency (what that branch currently always does) as well as concurrency with serial execution per client (what the released version currently for synchronous handlers, but not async
handlers). Serial per client execution is useful for stateful operations, hence why I'm likely to support it as well.
from securexpc.
Thanks for the feedback. I've gone with the former approach along with improved documentation. This has now been incorporated into 0.7.0.
from securexpc.
I noticed the following in the
xpc_connection_set_target_queue
documentation
Ah, indeed that's the behavior you're getting as described. Using a concurrent queue with an XPCServer will cause concurrent handlers to run if the requests are from different clients, but not concurrently from the same client.
I have ideas of how to change this behavior so calls from the same client are (mostly) concurrent, but will need to give it some thought.
from securexpc.
It seems to me that SecureXPC provides:
- a Swift concurrency API for both the client (suitable for 10.15+) and the server handlers (unfortunately only Monterey+ thanks to Apple)
- a closure-based API (suitable for 10.10+) but only for the clientβthere's no provision for handlers to call a completion callback, I think?
Is it feasible to add a completion callback API to the server handlers? Sounds like it would be a lot of work, and only useful for pre-Monterey :(
from securexpc.
a closure-based API (suitable for 10.10+) but only for the client
The server API is exclusively closure-based. However, your issue with it is that the closures are never called concurrently for requests from the same client. If they were called concurrently, that would meet your needs. Is that a correct understanding?
from securexpc.
Yes indeed, concurrently-called handlers would be great. It would also fit nicely with the client / server / routes metaphor, at least in my mind. I have to be honest β to date I assumed that the handlers I'd written using async
were all running concurrently.
For what it's worth, when I said there's no closure-based API on the server side, I meant in the sense that you currently provide both async
and synchronous versions of the four registerRoute
funcs, but no provision for an old-school "completion callback" style of async routes. The latter would be an async handler solution suitable for pre-macOS 10.15.
Since the route sync/async status has no bearing on whether it's actually called sync/async'ly, I'm not certain how relevant the above paragraph is now though.
Sorry if I seem to have an odd perspective on all this! My app is massively Promises-based, including the previous incarnation of my helper code (it all predates Swift's new Concurrency). So when I converted my old helper to leverage SecureXPC it was all with a promises / completion-handler mentality, in which virtually everything is running asynchronously.
from securexpc.
Try out this branch and let me know if this behaves the way you're expecting.
I have to be honest β to date I assumed that the handlers I'd written using
async
were all running concurrently.
They are (well the degree of concurrency is up to the Swift runtime to decide), it's the synchronous ones that were not. This difference in behavior was not intentional.
I meant in the sense that you currently provide both
async
and synchronous versions of the fourregisterRoute
funcs, but no provision for an old-school "completion callback" style of async routes.
I'm not 100% sure what you have in mind, but I think there is actually what you describe, but may not be for your use case. There are in fact six versions of the registerRoute
functions and the other two pass the registered closure a SequentialResultProvider
instance which can be used at future points in time (and from any thread). However, this is intended for long running (or even indefinite) actions where the client needs the latest data as it becomes available.
from securexpc.
I'm trying it now, thanks! My first attempt is returning:
failure(SecureXPC.XPCError.decodingError("valueNotFound(Foundation.UUID, Swift.DecodingError.Context(codingPath: [], debugDescription: "Key not present: __request_id", underlyingError: nil))"))
...after my handler completes. Just checking through my testing code to see if I'm doing something silly.
from securexpc.
SwiftAuthorizationApp
also returns the above error for me on its stock routes, when I upgrade its SecureXPC dependency to the concurrency branch.
For this branch, should I be setting server.targetQueue = DispatchQueue.global()
?
(Although I've tried it with and without, and still get the error)
from securexpc.
π Horray, it works!
(would you believe I was forgetting to update the helper β I'm so used to the awesome self-updating mechanism provided by SwiftAuthorizationHelperTool/Update.swift
)
This is exactly what I was hoping for. I've added two dummy routes which call these handlers:
static func testHandlerOne(withMsg msg: String) throws -> String {
print("starting handler one")
sleep(4)
return "Handler one responds with \(msg)"
}
static func testHandlerTwo(withMsg msg: String) throws -> String {
print("starting handler two")
let process = Process()
process.launchPath = "/bin/sleep"
process.arguments = ["4"]
process.launch()
process.waitUntilExit()
return "Handler two responds with \(msg)"
}
I can call any combination of these multiple times, rapid-fire, and after four seconds the responses from both all come back rapid-fire as expected.
This is fantastic, thanks again. Tomorrow I'll begin porting this into my app; it may take me some time as I have some handlers which leverage Swift's async
so I'll need to change what I'm doing there. Still, I think this will actually simplify my code overall, as a side-benefit. And be Catalina-compatible :)
from securexpc.
@jeff-h Would you be up for trying out the server-concurrency branch and letting me know if it works properly for you (I hope so as I wrote some automated tests) and what you think of the API design.
There's no longer an ability to set a DispatchQueue
, instead XPCServer
has a handlerConcurrency
property that by default is concurrent
and could also be set to serialPerClient
or serialPerServer
. This behavior is consistent regardless of whether the registered handlers are synchronous or async
.
I'm not sure which branch I'm going to go with. This one offers more customization, but I've yet to decide if it's worth the additional (framework internal) complexity.
from securexpc.
Trying it now.
from securexpc.
Using this new branch my app builds and runs seamlessly without any code changes, and appears to function as expected π
Regarding the new functionality, I'm vastly under-qualified to offer an opinion on any of it lol but nonetheless...
- from what I gather the concurrency options are all-or-nothing. In my particular use-case it's possible I would need most requests to run concurrently, and some requests to run serially. However, regardless of the capabilities of the server, my instinct would be to take care of any serial requirement on the client side. My views on all of this are probably heavily influenced by my day job (web development) :)
- the fact that handlers are run according to the overall server's
handlerConcurrency
property makes sense, but I think there's probably an implication that how they're registered (synchronous orasync
) would impact this. Perhaps a line in the documentation is all it would take to clarify that though.
from securexpc.
Related Issues (20)
- Transfer MTLSharedTextureHandle HOT 1
- SMAppService and MachServiceCriteria HOT 12
- setErrorHandler won't be called when using on server with startAndBlock HOT 5
- Validation fails for sandboxed Mach service HOT 1
- Sandbox memory exhaustion
- Add async variants of `XPCClient.send/sendMessage(...)` functions HOT 1
- Type errors in routes are conflated with missing routes HOT 2
- Add real XPC integration tests HOT 8
- Sample use case
- Verify that exporting a connection for a Mach service works correctly HOT 2
- Add support for client security requirements in anonymous services
- Throw error when attempting to reconnect to an anonymous service
- Document `startAndBlock()` must be called from main thread
- Verify that `endpoint` works for `XPCServiceServer` HOT 1
- Creating an `XPCAnonymousServer` or `XPCMachServer` and never starting it results in XPC API Misuse
- Client-level error handling HOT 6
- `XPC_ERROR_CONNECTION_INTERRUPTED` doesn't appear to actually behave as documented HOT 4
- [help] How can I use FileHandle as argument of withMessageType HOT 3
- Helper crashing in Catalina & Big Sur. HOT 9
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from securexpc.