Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

XMPPStream now retains activated modules. This fixes some outstanding…

… bugs and crashes related to the module plug-in system.
  • Loading branch information...
commit aa2e3d196bfd98e0e473cc756be70c837bfec738 1 parent a51eaba
@robbiehanson authored
Showing with 10 additions and 55 deletions.
  1. +1 −49 Core/XMPPModule.m
  2. +1 −2  Core/XMPPStream.h
  3. +8 −4 Core/XMPPStream.m
View
50 Core/XMPPModule.m
@@ -49,42 +49,7 @@ - (id)initWithDispatchQueue:(dispatch_queue_t)queue
- (void)dealloc
{
- if (xmppStream)
- {
- // It is dangerous to rely on the dealloc method to deactivate a module.
- //
- // Why?
- // Because when a module is activated, it is added as a delegate to the xmpp stream.
- // In addition to this, the module may be added as a delegate to various other xmpp components.
- // As per usual, these delegate references do NOT retain this module.
- // This means that modules may get invoked after they are deallocated.
- //
- // Consider the following example:
- //
- // 1. Thread A: Module is created (alloc/init) (retainCount = 1)
- // 2. Thread A: Module is activated (retainCount = 1)
- // 3. Thread A: Module is released, and dealloc is called.
- // First [MyCustomModule dealloc] is invoked.
- // Then [XMPPModule dealloc] is invoked.
- // Only at this point is [XMPPModule deactivate] run.
- // Since the deactivate method is synchronous,
- // it blocks until the module is removed as a delegate from the stream and all other modules.
- // 4. Thread B: Invokes a delegate method on our module ([XMPPModule deactivate] is waiting on thread B).
- // 5. Thread A: The [XMPPModule deactivate] method returns, but the damage is done.
- // Thread B has asynchronously dispatched a delegate method set to run on our module.
- // 6. Thread A: The dealloc method completes, and our module is now deallocated.
- // 7. Thread C: The delegate method attempts to run on our module, which is deallocated,
- // the application crashes, the computer blows up, and a meteor hits your favorite restaurant.
-
- XMPPLogWarn(@"%@: Deallocating activated module. You should deactivate modules before their final release.",
- NSStringFromClass([self class]));
-
- [self deactivate];
- }
-
-
dispatch_release(moduleQueue);
-
}
/**
@@ -148,20 +113,7 @@ - (void)deactivate
- (dispatch_queue_t)moduleQueue
{
- if (dispatch_get_current_queue() == moduleQueue)
- {
- return moduleQueue;
- }
- else
- {
- __block dispatch_queue_t result;
-
- dispatch_sync(moduleQueue, ^{
- result = moduleQueue;
- });
-
- return result;
- }
+ return moduleQueue;
}
- (XMPPStream *)xmppStream
View
3  Core/XMPPStream.h
@@ -8,7 +8,6 @@
#endif
@class XMPPSRVResolver;
-@class DDList;
@class XMPPParser;
@class XMPPJID;
@class XMPPIQ;
@@ -77,7 +76,7 @@ typedef enum XMPPStreamErrorCode XMPPStreamErrorCode;
NSTimeInterval lastSendReceiveTime;
NSData *keepAliveData;
- DDList *registeredModules;
+ NSMutableArray *registeredModules;
NSMutableDictionary *autoDelegateDict;
XMPPSRVResolver *srvResolver;
View
12 Core/XMPPStream.m
@@ -119,7 +119,7 @@ - (void)commonInit
keepAliveInterval = DEFAULT_KEEPALIVE_INTERVAL;
keepAliveData = [@" " dataUsingEncoding:NSUTF8StringEncoding];
- registeredModules = [[DDList alloc] init];
+ registeredModules = [[NSMutableArray alloc] init];
autoDelegateDict = [[NSMutableDictionary alloc] init];
receipts = [[NSMutableArray alloc] init];
@@ -3468,7 +3468,7 @@ - (void)registerModule:(XMPPModule *)module
// Register module
- [registeredModules add:(__bridge void *)module];
+ [registeredModules addObject:module];
// Add auto delegates (if there are any)
@@ -3526,7 +3526,7 @@ - (void)unregisterModule:(XMPPModule *)module
// Unregister modules
- [registeredModules remove:(__bridge void *)module];
+ [registeredModules removeObject:module];
}};
@@ -3563,7 +3563,6 @@ - (void)autoAddDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQue
// It will be added as a delegate to future registered modules of the given class.
id delegates = [autoDelegateDict objectForKey:className];
-
if (delegates == nil)
{
delegates = [[GCDMulticastDelegate alloc] init];
@@ -3629,6 +3628,11 @@ - (void)removeAutoDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegate
GCDMulticastDelegate *delegates = [autoDelegateDict objectForKey:className];
[delegates removeDelegate:delegate delegateQueue:delegateQueue];
+
+ if ([delegates count] == 0)
+ {
+ [autoDelegateDict removeObjectForKey:className];
+ }
}
}};
Please sign in to comment.
Something went wrong with that request. Please try again.