Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Use __CFPREFERENCES_AVOID_DAEMON = YES to fix pref clobbering

From @fpotter:

The problem is that preference values are causing SenTestinkgKit + XCTest to prematurely run tests... when all we wanted to do was query the tests in the bundle.

Here's what happens ...

    otest-query loads the test bundle.
    the test bundle links SenTestingKit, so dyld goes a ahead and loads SenTestingKit.
    SenTestingKit has an initialization function (i.e. marked with __attribute__((constructor))), so dyld runs that.
    The initialization function checks to see if the SenTest preference value is set. If so, it starts running tests immediately. (At this point, we haven't even gotten back to otest-query yet - it's still waiting for the bundle to finish loading).
    As soon as SenTestingKit has finished running the tests, it exits. We never return to otest-query.

So, the idea here was to clear the value of the SenTest preference before loading the test bundle. That should work... but it seems to fail intermittently, and I think I now know why.

You would assume the prefs values are read/written from ~/Library/Preferences/<app name>.plist. You would also think that prefs values are never synchronized until you explicitly call /synchronize/. That's what I thought, anyway.

As it turns out, there's actually a system service called cfprefsd that manages preferences and reading/writing them from the Preferences directory. It also caches preference values. If we're running otest-query processes in parallel, and they're each reading/writing via this daemon... it'd be expected for them to eventually stomp on each other.

But, there seems to be a way to disable the daemon usage, so I think we should do that. If you set __CFPREFERENCES_AVOID_DAEMON=YES in the environment before running otest-query, we'll be guaranteed that it won't read data from cfprefsd. That should give us more deterministic behavior. Also, I bet this makes it so that defaults are only synchronized when we explicitly call synchronize.
  • Loading branch information...
commit 8e5de53e7bebc45473ab9e4425bbef1abe18df4b 1 parent 0755ba3
@LegNeato LegNeato authored
View
1  xctool/xctool/OCUnitIOSAppTestQueryRunner.m
@@ -33,6 +33,7 @@ - (NSTask *)createTaskForQuery
@{@"DYLD_INSERT_LIBRARIES" : [XCToolLibPath() stringByAppendingPathComponent:@"otest-query-lib-ios.dylib"],
// The test bundle that we want to query from, as loaded by otest-query-lib-ios.dylib.
@"OtestQueryBundlePath" : [self bundlePath],
+ @"__CFPREFERENCES_AVOID_DAEMON" : @"YES",
});
}
View
2  xctool/xctool/OCUnitIOSLogicTestQueryRunner.m
@@ -30,7 +30,7 @@ - (NSTask *)createTaskForQuery
version,
[XCToolLibExecPath() stringByAppendingPathComponent:@"otest-query-ios"],
@[[self bundlePath]],
- @{});
+ @{@"__CFPREFERENCES_AVOID_DAEMON" : @"YES"});
}
@end
View
1  xctool/xctool/OCUnitOSXAppTestQueryRunner.m
@@ -37,6 +37,7 @@ - (NSTask *)createTaskForQuery
@"DYLD_FALLBACK_FRAMEWORK_PATH" : [XcodeDeveloperDirPath() stringByAppendingPathComponent:@"Library/Frameworks"],
@"NSUnbufferedIO" : @"YES",
@"OBJC_DISABLE_GC" : @"YES",
+ @"__CFPREFERENCES_AVOID_DAEMON" : @"YES",
}];
return task;
View
1  xctool/xctool/OCUnitOSXLogicTestQueryRunner.m
@@ -36,6 +36,7 @@ - (NSTask *)createTaskForQuery
@"DYLD_FALLBACK_FRAMEWORK_PATH" : [XcodeDeveloperDirPath() stringByAppendingPathComponent:@"Library/Frameworks"],
@"NSUnbufferedIO" : @"YES",
@"OBJC_DISABLE_GC" : @"YES",
+ @"__CFPREFERENCES_AVOID_DAEMON" : @"YES",
}];
return task;
Please sign in to comment.
Something went wrong with that request. Please try again.