Permalink
Browse files

-[TD_Server close] should be synchronous

Closing the server at app quit time is currently a race condition because the -close call returns before the server thread has finished closing stuff, so the process might exit before it finishes. Fixed this by making the -close call synchronous. (Related to #189.)
  • Loading branch information...
snej committed Nov 16, 2012
1 parent 7373805 commit c2e9855a6813cfbc5e627a98d6c41f071747e94c
Showing with 29 additions and 2 deletions.
  1. +5 −0 Demo-Mac/DemoAppController.m
  2. +2 −1 Source/TD_DatabaseManager.m
  3. +1 −0 Source/TD_Server.h
  4. +21 −1 Source/TD_Server.m
@@ -114,6 +114,11 @@ - (void) applicationDidFinishLaunching: (NSNotification*)n {
}
+- (IBAction) applicationWillTerminate:(id)sender {
+ [(CouchTouchDBServer*)_database.server close];
+}
+
+
- (IBAction) compact: (id)sender {
[_database compact];
}
@@ -172,13 +172,14 @@ - (NSArray*) allOpenDatabases {
- (void) close {
- LogTo(TD_Server, @"CLOSE %@", self);
+ LogTo(TD_Server, @"CLOSING %@ ...", self);
[_replicatorManager stop];
_replicatorManager = nil;
for (TD_Database* db in _databases.allValues) {
[db close];
}
[_databases removeAllObjects];
+ LogTo(TD_Server, @"CLOSED %@", self);
}
View
@@ -31,6 +31,7 @@
- (void) queue: (void(^)())block;
- (void) tellDatabaseManager: (void (^)(TD_DatabaseManager*))block;
- (void) tellDatabaseNamed: (NSString*)dbName to: (void (^)(TD_Database*))block;
+- (id) waitForDatabaseManager: (id (^)(TD_DatabaseManager*))block;
- (void) close;
View
@@ -79,10 +79,13 @@ - (void)dealloc
- (void) close {
if (_serverThread) {
- [self queue: ^{
+ [self waitForDatabaseManager:^id(TD_DatabaseManager* mgr) {
LogTo(TD_Server, @"Stopping server thread...");
[TDURLProtocol unregisterServer: self];
+ [_manager close];
+ _manager = nil;
_stopRunLoop = YES;
+ return nil;
}];
_serverThread = nil;
}
@@ -140,6 +143,23 @@ - (void) tellDatabaseManager: (void (^)(TD_DatabaseManager*))block {
}
+- (id) waitForDatabaseManager: (id (^)(TD_DatabaseManager*))block {
+ __block id result = nil;
+ NSConditionLock* lock = [[NSConditionLock alloc] initWithCondition: 0];
+ [self queue: ^{
+ [lock lockWhenCondition: 0];
+ @try {
+ result = block(_manager);
+ } @finally {
+ [lock unlockWithCondition: 1];
+ }
+ }];
+ [lock lockWhenCondition: 1]; // wait till block finishes
+ [lock unlock];
+ return result;
+}
+
+
@end

0 comments on commit c2e9855

Please sign in to comment.