task_set_bootstrap_port in parent causes child to hang
The behavior of task_set_bootstrap_port
has changed between OS X 10.6 and 10.7. In 10.6, this worked:
// parent process
mach_port_t parent_recv_port = MACH_PORT_NULL;
setup_recv_port (&parent_recv_port);
task_set_bootstrap_port(mach_task_self(), parent_recv_port);
NSTask *qtTask = [[NSTask alloc] init];
[qtTask setLaunchPath:...];
[qtTask launch];
...
// child process
int main (int argc, const char * argv[])
{
mach_port_t parent_recv_port = MACH_PORT_NULL;
task_get_bootstrap_port(mach_task_self(), &parent_recv_port);
...
}
In 10.7, however, the child process does not execute the first line of main
immediately after the parent calls -launch
-- it waits until the parent process terminates. (Though the child process does immediately show up in ps
.)
I've narrowed the problem down to the call to task_set_bootstrap_port
. When the call is absent, the child process does not hang. And, if I restore the bootstrap port to the original immediately after task_set_bootstrap_port
--
task_set_bootstrap_port(mach_task_self(), bootstrap_port);
-- then the child pr开发者_JS百科ocess also does not hang.
Error handling code has been omitted from above, but in reality it's checking for errors after every call. No errors.
So, any idea why the behavior of task_set_bootstrap_port
has changed from 10.6 to 10.7? And is there a workaround?
Constraints:
- Need access to a
mach_port_t
to pass toIOSurfaceLookupFromMachPort
. - Runloop may not exist, so can't use
NSMachPort
orCFMachPort
.
Apple Developer Technical Support tells me that temporarily changing the bootstrap port, as this code was doing, was never guaranteed to work. In this case XPC was trying to message the boostrap port after it had been changed, and that was failing so things broke.
A quick fix is to use bootstrap_register
(though deprecated) in the parent process and bootstrap_look_up
in the child. This lets the child look up the parent by name (a string) and get a port from it.
精彩评论