[Interest] OS X Sandboxing and IPC (my experience so far)

Till Oliver Knoll till.oliver.knoll at gmail.com
Mon May 14 10:03:47 CEST 2012


Hi,

I thought I'd share some of my experience I made so far with regards
to Mac OS X "Sandboxing" and splitting my application into several
processes which then need to communicate with each other in some way
or another.

The idea is to give the parent process the "Entitlement" file access
(as specified by the user via file dialogs), but no network access.
The child process has no file access Entitlement at all, but does all
the networking. It is started via QProcess.

It was very tempting to start with the "communication via stdin/out"
approach, as QProcess API provides all we need: we get notified via
signal as soon as the child process writes something to its stdout. Do
requests via QProcess::write - easy. But as there seems to be no
straight-forward (platform-independent) way to "listen on stdin" in
the child process for incoming messages, and I need to send binary
data for which stdin/out is not suitable anyway, I abandoned this
approach for now (also refer to other discussion in "QProcess: child
read from stdin - no data received?").


My current approach involves starting a QLocalServer in the parent
process and connect to it in the child process. However my first naive
approach failed as soon as the application was "sandboxed":

  QLocalServer server;
  server.listen("my_port");

with some "Unknown Error: 1" message in errorString(). This is not
because the parent process doesn't have any network entitlements, but
simply because it cannot write to the file system but into its own
sandbox. And that's exactly the solution: make sure the "local socket"
is generated in the application's container, e.g. with:

  server.listen(QDir::homePath() + "/my_port");

Et voilĂ : server.fullServerName() now returns

  /Users/tknoll/Library/Containers/[Bundle ID]/Data/my_port

which is a valid location to write to :)


However I noticed a warning message in the console output which
appears just after the listen() call above:

  QSocketNotifier: Can only be used with threads started with QThread

regardless of whether I give the parent process (for testing purposes)
network entitlements (both send and receive) or not. I haven't done
any more coding so far, but I expect this approach to fail also, as
the server wouldn't probably accept any connections. This is with Qt
4.8.0, I just downloaded Qt 4.8.1 but haven't tried it yet - but I
expect the same result.

I don't get this warning message when the application is /not/
sandboxed. Anyone has any experience with that so far? Google turns up
with quite some result hits, but nothing seems to be related to
"sandboxing". I can only guess that the OS spawns a separate thread
for the sandboxed process (?), and this is what QSocketNotifier then
doesn't like.


By the way, the Proper Way To Do It(tm) is to use XPC (according to Apple):

  http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingXPCServices.html#//apple_ref/doc/uid/10000172i-SW6-SW1

But this is totally platform-dependent again, and I think if the
QLocalServer approach doesn't work I'll just revert to a "single
process that does it all" design :/


Anyone else trying to split up their "sandboxed" Qt application?

Cheers,
  Oliver



More information about the Interest mailing list