Using SCNetworkReachability from XPC Service

Hi,

I'm writing an XPC Service hosted in a container app.

This service is expected to trigger IPC when some URL of interest become reachable. I'm using SCNetworkReachability (Reachability class provided as sample code from Apple).

The reachability notification runs fine when running from the container app.

However the XPC Service is never triggered of any network change.

I'm suspecting something related to RunLoop or RunLoopMode (XPCListener is instantiated with serviceListener) but cannot find any fix.

I disabled sandboxing without success (and anyway it runs fine with sandboxed container + network client entitlement).

Any suggestion ?

Accepted Reply

How are you scheduling the SCNetworkReachability? Apple’s sample code for this using SCNetworkReachabilityScheduleWithRunLoop, which makes things tricky for an XPC service because, by default, they have don’t run the run loop. A better option for this environment is SCNetworkReachabilitySetDispatchQueue.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Replies

An update on this issue. When the service runs as agent it behave as expected.

i then assume this is related to some process privileges.

How are you scheduling the SCNetworkReachability? Apple’s sample code for this using SCNetworkReachabilityScheduleWithRunLoop, which makes things tricky for an XPC service because, by default, they have don’t run the run loop. A better option for this environment is SCNetworkReachabilitySetDispatchQueue.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I used the default SCNetworkReachabilityScheduleWithRunLoop from main source code during launch.

As the service is based on MachService name the resume method returns and I did setup a main run loop.

I tried also postponing SCNetworkReachabilityScheduleWithRunLoop using GCD (dispatch to main queue) and both solutions are running fine.

I’ll try SCNetworkReachabilitySetDispatchQueue As well to see potential benefits.

I did setup a main run loop.

Unless you have other code that specifically needs a main thread run loop, I encourage you to use the Dispatch queue variant and then terminate the main thread using dispatch_main (dispatchMain in Swift).

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi,

An update: as I use KVO on NSWorkspace main run loop remains mandatory (documented and tested).

Anyway I’m not sure if the difference is only footprint-relative or if there are more complex reason for going GCD only.

If you’re using types, like NSWorkspace, that require a main thread run loop, using SCNetworkReachabilityScheduleWithRunLoop with that run loop is absolutely fine.

Note that you can tell the XPC runtime to use such a runloop by setting the RunLoopType property to NSRunLoop. See the xpcservice.plist man page for details.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"