Skip to content

Commit 91787b9

Browse files
Merge pull request #198 from rabbitmq/rabbit-obj-client-194-take-4
Avoid memory leaks in RMQConnection dependency graph (take 4)
2 parents 389c7d2 + f8edec8 commit 91787b9

15 files changed

+721
-32
lines changed

RMQClient.xcodeproj/project.pbxproj

Lines changed: 637 additions & 1 deletion
Large diffs are not rendered by default.

RMQClient/RMQAllocatedChannel.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ @interface RMQAllocatedChannel ()
6060
@property (nonatomic, readwrite) NSNumber *prefetchCountPerChannel;
6161
@property (nonatomic, readwrite) id<RMQConnectionDelegate> delegate;
6262
@property (nonatomic, readwrite) id<RMQNameGenerator> nameGenerator;
63-
@property (nonatomic, readwrite) id<RMQChannelAllocator> allocator;
63+
@property (nonatomic, weak, readwrite) id<RMQChannelAllocator> allocator;
6464
@end
6565

6666
@implementation RMQAllocatedChannel

RMQClient/RMQChannelAllocator.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@
4545
#import "RMQSender.h"
4646

4747
@protocol RMQChannelAllocator <NSObject>
48-
@property (nonatomic, readwrite) id<RMQSender> sender;
48+
@property (nonatomic,weak, readwrite) id<RMQSender> sender;
4949
- (id<RMQChannel>)allocate;
5050
- (void)releaseChannelNumber:(NSNumber *)channelNumber;
5151
- (NSArray<id<RMQChannel>> *)allocatedUserChannels;
52+
- (void)cleanupOnClose;
53+
5254
@end

RMQClient/RMQConnection.m

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ @interface RMQConnection ()
6767
@property (nonatomic, readwrite) id <RMQFrameHandler> frameHandler;
6868
@property (nonatomic, readwrite) id<RMQLocalSerialQueue> commandQueue;
6969
@property (nonatomic, readwrite) id<RMQWaiterFactory> waiterFactory;
70-
@property (nonatomic, readwrite) id<RMQHeartbeatSender> heartbeatSender;
70+
@property (nonatomic, weak, readwrite) id<RMQHeartbeatSender> heartbeatSender;
7171
@property (nonatomic, weak, readwrite) id<RMQConnectionDelegate> delegate;
72-
@property (nonatomic, readwrite) id <RMQChannel> channelZero;
72+
@property (nonatomic, weak, readwrite) id <RMQChannel> channelZero;
7373
@property (nonatomic, readwrite) RMQConnectionConfig *config;
7474
@property (nonatomic, readwrite) NSMutableDictionary *userChannels;
7575
@property (nonatomic, readwrite) NSNumber *frameMax;
@@ -559,22 +559,24 @@ - (void)start:(void (^)(void))completionHandler {
559559
[self.delegate connection:self failedToConnectWithError:connectError];
560560
} else {
561561
[self.transport write:[RMQProtocolHeader new].amqEncoded];
562+
__weak id this = self;
562563

563564
[self.commandQueue enqueue:^{
564-
id<RMQWaiter> handshakeCompletion = [self.waiterFactory makeWithTimeout:self.handshakeTimeout];
565+
__strong typeof(self) strongThis = this;
566+
id<RMQWaiter> handshakeCompletion = [strongThis.waiterFactory makeWithTimeout:strongThis.handshakeTimeout];
565567

566-
RMQHandshaker *handshaker = [[RMQHandshaker alloc] initWithSender:self
567-
config:self.config
568+
RMQHandshaker *handshaker = [[RMQHandshaker alloc] initWithSender:strongThis
569+
config:strongThis.config
568570
completionHandler:^(NSNumber *heartbeatTimeout,
569571
RMQTable *serverProperties) {
570-
[self.heartbeatSender startWithInterval:@(heartbeatTimeout.integerValue / 2)];
571-
self.handshakeComplete = YES;
572+
[strongThis.heartbeatSender startWithInterval:@(heartbeatTimeout.integerValue / 2)];
573+
strongThis.handshakeComplete = YES;
572574
[handshakeCompletion done];
573-
[self.reader run];
574-
self.serverProperties = serverProperties;
575+
[strongThis.reader run];
576+
strongThis.serverProperties = serverProperties;
575577
completionHandler();
576578
}];
577-
RMQReader *handshakeReader = [[RMQReader alloc] initWithTransport:self.transport
579+
RMQReader *handshakeReader = [[RMQReader alloc] initWithTransport:strongThis.transport
578580
frameHandler:handshaker];
579581
handshaker.reader = handshakeReader;
580582
[handshakeReader run];
@@ -583,7 +585,7 @@ - (void)start:(void (^)(void))completionHandler {
583585
NSError *error = [NSError errorWithDomain:RMQErrorDomain
584586
code:RMQErrorConnectionHandshakeTimedOut
585587
userInfo:@{NSLocalizedDescriptionKey: @"Handshake timed out."}];
586-
[self.delegate connection:self failedToConnectWithError:error];
588+
[strongThis.delegate connection:strongThis failedToConnectWithError:error];
587589
}
588590
}];
589591
}
@@ -704,7 +706,16 @@ - (NSArray *)closeOperationsWithoutBlock {
704706
^{[self.heartbeatSender stop];},
705707
^{
706708
self.transport.delegate = nil;
709+
[self.transport cleanup];
707710
[self.transport close];
711+
},
712+
^{
713+
[self.channelAllocator cleanupOnClose];
714+
self.channelAllocator = nil;
715+
},
716+
^{
717+
self.reader = nil;
718+
self.frameHandler = nil;
708719
}];
709720
}
710721

@@ -716,7 +727,16 @@ - (NSArray *)closeOperations {
716727
^{[self.heartbeatSender stop];},
717728
^{
718729
self.transport.delegate = nil;
730+
[self.transport cleanup];
719731
[self.transport close];
732+
},
733+
^{
734+
[self.channelAllocator cleanupOnClose];
735+
self.channelAllocator = nil;
736+
},
737+
^{
738+
self.reader = nil;
739+
self.frameHandler = nil;
720740
}];
721741
}
722742

RMQClient/RMQConnectionRecover.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ @interface RMQConnectionRecover ()
4747
@property (nonatomic, readwrite) NSUInteger attempts;
4848
@property (nonatomic, readwrite) NSUInteger attemptLimit;
4949
@property (nonatomic, readwrite) BOOL onlyErrors;
50-
@property (nonatomic, readwrite) id<RMQHeartbeatSender> heartbeatSender;
50+
@property (nonatomic, weak, readwrite) id<RMQHeartbeatSender> heartbeatSender;
5151
@property (nonatomic, readwrite) id<RMQLocalSerialQueue> commandQueue;
5252
@property (nonatomic, readwrite) id<RMQConnectionDelegate> delegate;
5353
@end

RMQClient/RMQMultipleChannelAllocator.m

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,13 @@ - (instancetype)init {
8282
[self doesNotRecognizeSelector:_cmd];
8383
return nil;
8484
}
85-
85+
- (void)cleanupOnClose {
86+
for (id key in self.channels) {
87+
[[self.channels objectForKey:key] close];
88+
}
89+
[self.channels removeAllObjects];
90+
91+
}
8692
- (id<RMQChannel>)allocate {
8793
id<RMQChannel> ch;
8894
@synchronized(self) {

RMQClient/RMQReader.m

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
#import "RMQMethodDecoder.h"
4646

4747
@interface RMQReader ()
48-
@property (nonatomic, readwrite) id<RMQTransport>transport;
48+
@property (nonatomic,weak, readwrite) id<RMQTransport>transport;
4949
@property (nonatomic, readwrite) id<RMQFrameHandler>frameHandler;
5050
@end
5151

@@ -78,20 +78,22 @@ - (void)run {
7878

7979
- (void)handleMethodFrame:(RMQFrame *)frame {
8080
id<RMQMethod> method = (id<RMQMethod>)frame.payload;
81-
81+
__weak id this = self;
8282
if (method.hasContent) {
8383
[self.transport readFrame:^(NSData * _Nonnull headerData) {
84-
RMQFrame *headerFrame = [self frameWithData:headerData];
84+
__strong typeof(self) strongThis = this;
85+
86+
RMQFrame *headerFrame = [strongThis frameWithData:headerData];
8587
RMQContentHeader *header = (RMQContentHeader *)headerFrame.payload;
8688

8789
RMQFrameset *frameset = [[RMQFrameset alloc] initWithChannelNumber:frame.channelNumber
8890
method:method
8991
contentHeader:header
9092
contentBodies:@[]];
9193
if ([header.bodySize isEqualToNumber:@0]) {
92-
[self.frameHandler handleFrameset:frameset];
94+
[strongThis.frameHandler handleFrameset:frameset];
9395
} else {
94-
[self readBodiesForIncompleteFrameset:frameset];
96+
[strongThis readBodiesForIncompleteFrameset:frameset];
9597
}
9698
}];
9799
} else {
@@ -102,17 +104,18 @@ - (void)handleMethodFrame:(RMQFrame *)frame {
102104
}
103105

104106
- (void)readBodiesForIncompleteFrameset:(RMQFrameset *)contentFrameset {
107+
__weak id this = self;
105108
[self.transport readFrame:^(NSData * _Nonnull data) {
106109
RMQFrame *frame = [self frameWithData:data];
107-
110+
__strong typeof(self) strongThis = this;
108111
if ([frame.payload isKindOfClass:[RMQContentBody class]]) {
109-
[self frameset:contentFrameset
112+
[this frameset:contentFrameset
110113
addBodyFrame:frame];
111114
} else {
112-
[self.frameHandler handleFrameset:contentFrameset];
115+
[strongThis.frameHandler handleFrameset:contentFrameset];
113116
RMQFrameset *nonContentFrameset = [[RMQFrameset alloc] initWithChannelNumber:contentFrameset.channelNumber
114117
method:(id <RMQMethod>)frame.payload];
115-
[self.frameHandler handleFrameset:nonContentFrameset];
118+
[strongThis.frameHandler handleFrameset:nonContentFrameset];
116119
}
117120
}];
118121
}

RMQClient/RMQSuspendResumeDispatcher.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@
4646

4747
@interface RMQSuspendResumeDispatcher ()
4848
@property (nonatomic, readwrite) id<RMQChannel> channel;
49-
@property (nonatomic, readwrite) id<RMQSender> sender;
49+
@property (nonatomic,weak, readwrite) id<RMQSender> sender;
5050
@property (nonatomic, readwrite) RMQFramesetValidator *validator;
5151
@property (nonatomic, readwrite) id<RMQLocalSerialQueue> commandQueue;
5252
@property (nonatomic, readwrite) id<RMQLocalSerialQueue> enablementQueue;
5353
@property (nonatomic, readwrite) NSNumber *enableDelay;
54-
@property (nonatomic, readwrite) id<RMQConnectionDelegate> delegate;
54+
@property (nonatomic,weak, readwrite) id<RMQConnectionDelegate> delegate;
5555
@property (nonatomic, readwrite) DispatcherState state;
5656
@property (nonatomic, readwrite) BOOL disabled;
5757
@end

RMQClient/RMQSynchronizedMutableDictionary.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,5 @@
4747
- (nullable id)objectForKeyedSubscript:(nonnull id)key;
4848
- (void)setObject:(nonnull id)obj forKeyedSubscript:(nonnull id)key;
4949
- (void)removeObjectForKey:(nonnull id)key;
50+
- (void)removeAllObjects;
5051
@end

RMQClient/RMQSynchronizedMutableDictionary.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,11 @@ - (void)removeObjectForKey:(id)key {
7979
self.count--;
8080
}
8181
}
82+
- (void)removeAllObjects {
83+
@synchronized (self.lock) {
84+
[self.backingDictionary removeAllObjects];
85+
self.count = 0;
86+
}
87+
}
8288

8389
@end

0 commit comments

Comments
 (0)