Skip to content

Commit 81f6e70

Browse files
6.4.19-b4 (#1595)
- Added even more debug logging - Fixed crash when opening a new chat that wasn't listed as active before - Moved heavy deallocation work to a background task to make initial connection faster
2 parents 3312e33 + dff4c2b commit 81f6e70

File tree

3 files changed

+74
-7
lines changed

3 files changed

+74
-7
lines changed

Monal/Classes/ActiveChatsViewController.m

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,8 +569,11 @@ -(void) insertOrMoveContact:(MLContact*) contact completion:(void (^ _Nullable)(
569569
[insertContactToArray insertObject:contact atIndex:0];
570570
[self.chatListTable insertRowsAtIndexPaths:@[insertAtPath] withRowAnimation:UITableViewRowAnimationRight];
571571
//make sure to fully refresh to remove the empty dataset (yes this will trigger on first chat pinning, too, but that does no harm)
572+
//but make sure to not do this nested inside our current performBatchUpdates call!
572573
if(oldCount == 0)
573-
[self refreshDisplay];
574+
dispatch_async(dispatch_get_main_queue(), ^{
575+
[self refreshDisplay];
576+
});
574577
}
575578
} completion:^(BOOL finished) {
576579
if(completion) completion(finished);

Monal/Classes/HelperTools.m

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2162,6 +2162,11 @@ +(void) installCrashHandler
21622162
KSCrash* handler = [KSCrash sharedInstance];
21632163
handler.basePath = [[HelperTools getContainerURLForPathComponents:@[@"CrashReports"]] path];
21642164
handler.monitoring = KSCrashMonitorTypeProductionSafe; //KSCrashMonitorTypeAll
2165+
//don't try to debug zombies if not in debug mode
2166+
//#ifndef DEBUG
2167+
#ifndef IS_ALPHA
2168+
handler.monitoring = handler.monitoring & (~KSCrashMonitorTypeZombie);
2169+
#endif
21652170
handler.onCrash = crash_callback;
21662171
//this can trigger crashes on macos < 13 (e.g. mac catalyst < 16) (and possibly ios < 16)
21672172
#if !TARGET_OS_MACCATALYST

Monal/Classes/xmpp.m

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,7 +1010,7 @@ -(void) disconnectWithStreamError:(MLXMLNode* _Nullable) streamError andExplicit
10101010

10111011
//reset smacks state to sane values (this can be done even if smacks is not supported)
10121012
[self initSM3];
1013-
self.unAckedStanzas = stanzas;
1013+
[self replaceUnackedStanzasWith:stanzas];
10141014

10151015
//inform all old iq handlers of invalidation and clear _iqHandlers dictionary afterwards
10161016
@synchronized(self->_iqHandlers) {
@@ -1142,7 +1142,7 @@ -(void) disconnectWithStreamError:(MLXMLNode* _Nullable) streamError andExplicit
11421142

11431143
//reset smacks state to sane values (this can be done even if smacks is not supported)
11441144
[self initSM3];
1145-
self.unAckedStanzas = stanzas;
1145+
[self replaceUnackedStanzasWith:stanzas];
11461146

11471147
//inform all old iq handlers of invalidation and clear _iqHandlers dictionary afterwards
11481148
@synchronized(self->_iqHandlers) {
@@ -1670,7 +1670,7 @@ -(void) resendUnackedStanzas
16701670
self.lastOutboundStanza = [NSNumber numberWithInteger:[self.lastOutboundStanza integerValue] - [self.unAckedStanzas count]];
16711671
//Send appends to the unacked stanzas. Not removing it now will create an infinite loop.
16721672
//It may also result in mutation on iteration
1673-
[self.unAckedStanzas removeAllObjects];
1673+
[self replaceUnackedStanzasWith:[NSMutableArray new]];
16741674
for(NSDictionary* dic in sendCopy)
16751675
[self send:(XMPPStanza*)[dic objectForKey:kStanza]];
16761676
DDLogInfo(@"Done resending unacked stanzas...");
@@ -1804,7 +1804,7 @@ -(BOOL) removeAckedStanzasFromQueue:(NSNumber*) hvalue
18041804
}
18051805

18061806
[iterationArray removeObjectsInArray:discard];
1807-
self.unAckedStanzas = iterationArray;
1807+
[self replaceUnackedStanzasWith:iterationArray];
18081808

18091809
//persist these changes (but only if we actually made some changes)
18101810
if([discard count])
@@ -3823,6 +3823,7 @@ -(void) realReadState
38233823
NSMutableDictionary* dic = [[DataLayer sharedInstance] readStateForAccount:self.accountNo];
38243824
if(dic)
38253825
{
3826+
DDLogError(@"Inside dic if...");
38263827
//check state version
38273828
int oldVersion = [dic[@"VERSION"] intValue];
38283829
if(oldVersion != STATE_VERSION)
@@ -3835,150 +3836,188 @@ -(void) realReadState
38353836
self.hasSeenOmemoDeviceListAfterOwnDeviceid = YES;
38363837
}
38373838

3839+
DDLogError(@"Collecting smacks state...");
38383840
//collect smacks state
38393841
self.lastHandledInboundStanza = [dic objectForKey:@"lastHandledInboundStanza"];
38403842
self.lastHandledOutboundStanza = [dic objectForKey:@"lastHandledOutboundStanza"];
38413843
self.lastOutboundStanza = [dic objectForKey:@"lastOutboundStanza"];
3844+
DDLogError(@"Collecting stanzas...");
38423845
NSArray* stanzas = [dic objectForKey:@"unAckedStanzas"];
3843-
self.unAckedStanzas = [stanzas mutableCopy];
3846+
[self replaceUnackedStanzasWith:[stanzas mutableCopy]];
3847+
DDLogError(@"Done collecting stanzas...");
38443848
self.streamID = [dic objectForKey:@"streamID"];
38453849
if([dic objectForKey:@"isDoingFullReconnect"])
38463850
{
3851+
DDLogError(@"Inside is doing full reconnect...");
38473852
NSNumber* isDoingFullReconnect = [dic objectForKey:@"isDoingFullReconnect"];
38483853
self.isDoingFullReconnect = isDoingFullReconnect.boolValue;
38493854
}
38503855

3856+
DDLogError(@"Checking for corrupt smacks state...");
38513857
//invalidate corrupt smacks states (this could potentially loose messages, but hey, the state is corrupt anyways)
38523858
if(self.lastHandledInboundStanza == nil || self.lastHandledOutboundStanza == nil || self.lastOutboundStanza == nil || !self.unAckedStanzas)
38533859
{
3860+
DDLogError(@"Inside corrupt smacks state...");
38543861
#ifndef IS_ALPHA
38553862
[self initSM3];
38563863
#else
38573864
@throw [NSException exceptionWithName:@"RuntimeError" reason:@"corrupt smacks state" userInfo:dic];
38583865
#endif
38593866
}
38603867

3868+
DDLogError(@"Handling iq handlers...");
38613869
NSDictionary* persistentIqHandlers = [dic objectForKey:@"iqHandlers"];
38623870
NSMutableDictionary* persistentIqHandlerDescriptions = [NSMutableDictionary new];
3871+
DDLogError(@"Before iq handlers @synchronized...");
38633872
@synchronized(_iqHandlers) {
3873+
DDLogError(@"Inside iq handlers @synchronized...");
38643874
//remove all current persistent handlers...
38653875
NSMutableDictionary* handlersCopy = [_iqHandlers copy];
38663876
for(NSString* iqid in handlersCopy)
38673877
if(handlersCopy[iqid][@"handler"] != nil)
38683878
[_iqHandlers removeObjectForKey:iqid];
3879+
DDLogError(@"all persistent handlers removed...");
38693880
//...and replace them with persistent handlers loaded from state
38703881
for(NSString* iqid in persistentIqHandlers)
38713882
{
38723883
_iqHandlers[iqid] = [persistentIqHandlers[iqid] mutableCopy];
38733884
persistentIqHandlerDescriptions[iqid] = [NSString stringWithFormat:@"%@: %@", persistentIqHandlers[iqid][@"timeout"], persistentIqHandlers[iqid][@"handler"]];
38743885
}
3886+
DDLogError(@"replaced persistent handlers from state...");
38753887
}
38763888

3889+
DDLogError(@"after iq handers @synchronized and before reconnection handlers @synchronized...");
3890+
38773891
@synchronized(self->_reconnectionHandlers) {
3892+
DDLogError(@"inside reconnection handlers @synchronized...");
38783893
[_reconnectionHandlers removeAllObjects];
38793894
[_reconnectionHandlers addObjectsFromArray:[dic objectForKey:@"reconnectionHandlers"]];
3895+
DDLogError(@"did work...");
38803896
}
3897+
DDLogError(@"after reconnection handlers @synchronized...");
38813898

38823899
self.connectionProperties.serverFeatures = [dic objectForKey:@"serverFeatures"];
38833900
self.connectionProperties.serverDiscoFeatures = [dic objectForKey:@"serverDiscoFeatures"];
38843901
self.connectionProperties.accountDiscoFeatures = [dic objectForKey:@"accountDiscoFeatures"];
3902+
DDLogError(@"after disco update 1...");
38853903

38863904
self.connectionProperties.discoveredServices = [[dic objectForKey:@"discoveredServices"] mutableCopy];
38873905
self.connectionProperties.discoveredStunTurnServers = [[dic objectForKey:@"discoveredStunTurnServers"] mutableCopy];
38883906
self.connectionProperties.discoveredAdhocCommands = [[dic objectForKey:@"discoveredAdhocCommands"] mutableCopy];
38893907
self.connectionProperties.serverVersion = [dic objectForKey:@"serverVersion"];
3908+
DDLogError(@"after disco upodate 2...");
38903909

38913910
self.connectionProperties.uploadServer = [dic objectForKey:@"uploadServer"];
38923911
self.connectionProperties.conferenceServers = [[dic objectForKey:@"conferenceServers"] mutableCopy];
3912+
DDLogError(@"after server update...");
38933913

38943914
if([dic objectForKey:@"loggedInOnce"])
38953915
{
38963916
NSNumber* loggedInOnce = [dic objectForKey:@"loggedInOnce"];
38973917
_loggedInOnce = loggedInOnce.boolValue;
38983918
}
3919+
DDLogError(@"after logged in once...");
38993920

39003921
if([dic objectForKey:@"usingCarbons2"])
39013922
{
39023923
NSNumber* carbonsNumber = [dic objectForKey:@"usingCarbons2"];
39033924
self.connectionProperties.usingCarbons2 = carbonsNumber.boolValue;
39043925
}
3926+
DDLogError(@"after carbons2...");
39053927

39063928
if([dic objectForKey:@"supportsBookmarksCompat"])
39073929
{
39083930
NSNumber* compatNumber = [dic objectForKey:@"supportsBookmarksCompat"];
39093931
self.connectionProperties.supportsBookmarksCompat = compatNumber.boolValue;
39103932
}
3933+
DDLogError(@"after bookmarks compat...");
39113934

39123935
if([dic objectForKey:@"pushEnabled"])
39133936
{
39143937
NSNumber* pushEnabled = [dic objectForKey:@"pushEnabled"];
39153938
self.connectionProperties.pushEnabled = pushEnabled.boolValue;
39163939
}
3940+
DDLogError(@"after push enabled...");
39173941

39183942
if([dic objectForKey:@"supportsPubSub"])
39193943
{
39203944
NSNumber* supportsPubSub = [dic objectForKey:@"supportsPubSub"];
39213945
self.connectionProperties.supportsPubSub = supportsPubSub.boolValue;
39223946
}
3947+
DDLogError(@"after supports push...");
39233948

39243949
if([dic objectForKey:@"supportsPubSubMax"])
39253950
{
39263951
NSNumber* supportsPubSubMax = [dic objectForKey:@"supportsPubSubMax"];
39273952
self.connectionProperties.supportsPubSubMax = supportsPubSubMax.boolValue;
39283953
}
3954+
DDLogError(@"after supports pubsub max...");
39293955

39303956
if([dic objectForKey:@"supportsModernPubSub"])
39313957
{
39323958
NSNumber* supportsModernPubSub = [dic objectForKey:@"supportsModernPubSub"];
39333959
self.connectionProperties.supportsModernPubSub = supportsModernPubSub.boolValue;
39343960
}
3961+
DDLogError(@"after supports modern pubsub...");
39353962

39363963
if([dic objectForKey:@"supportsHTTPUpload"])
39373964
{
39383965
NSNumber* supportsHTTPUpload = [dic objectForKey:@"supportsHTTPUpload"];
39393966
self.connectionProperties.supportsHTTPUpload = supportsHTTPUpload.boolValue;
39403967
}
3968+
DDLogError(@"after supports http upload...");
39413969

39423970
if([dic objectForKey:@"lastInteractionDate"])
39433971
_lastInteractionDate = [dic objectForKey:@"lastInteractionDate"];
3972+
DDLogError(@"after last interaction date...");
39443973

39453974
if([dic objectForKey:@"accountDiscoDone"])
39463975
{
39473976
NSNumber* accountDiscoDone = [dic objectForKey:@"accountDiscoDone"];
39483977
self.connectionProperties.accountDiscoDone = accountDiscoDone.boolValue;
39493978
}
3979+
DDLogError(@"after account disco done...");
39503980

39513981
if([dic objectForKey:@"pubsubData"])
39523982
[self.pubsub setInternalData:[dic objectForKey:@"pubsubData"]];
3983+
DDLogError(@"after pubsub data...");
39533984

39543985
if([dic objectForKey:@"mucState"])
39553986
[self.mucProcessor setInternalState:[dic objectForKey:@"mucState"]];
3987+
DDLogError(@"after muc state...");
39563988

39573989
if([dic objectForKey:@"runningCapsQueries"])
39583990
_runningCapsQueries = [[dic objectForKey:@"runningCapsQueries"] mutableCopy];
3991+
DDLogError(@"after running caps queries...");
39593992

39603993
if([dic objectForKey:@"runningMamQueries"])
39613994
_runningMamQueries = [[dic objectForKey:@"runningMamQueries"] mutableCopy];
3995+
DDLogError(@"after runing mam queries...");
39623996

39633997
if([dic objectForKey:@"inCatchup"])
39643998
_inCatchup = [[dic objectForKey:@"inCatchup"] mutableCopy];
3999+
DDLogError(@"after in catchup...");
39654000

39664001
if([dic objectForKey:@"mdsData"])
39674002
_mdsData = [[dic objectForKey:@"mdsData"] mutableCopy];
4003+
DDLogError(@"after mds data...");
39684004

39694005
if([dic objectForKey:@"cachedStreamFeaturesBeforeAuth"])
39704006
_cachedStreamFeaturesBeforeAuth = [dic objectForKey:@"cachedStreamFeaturesBeforeAuth"];
39714007
if([dic objectForKey:@"cachedStreamFeaturesAfterAuth"])
39724008
_cachedStreamFeaturesAfterAuth = [dic objectForKey:@"cachedStreamFeaturesAfterAuth"];
4009+
DDLogError(@"after cached features...");
39734010

39744011
if([dic objectForKey:@"omemoState"] && self.omemo)
39754012
self.omemo.state = [dic objectForKey:@"omemoState"];
4013+
DDLogError(@"after omemo state...");
39764014

39774015
if([dic objectForKey:@"hasSeenOmemoDeviceListAfterOwnDeviceid"])
39784016
{
39794017
NSNumber* hasSeenOmemoDeviceListAfterOwnDeviceid = [dic objectForKey:@"hasSeenOmemoDeviceListAfterOwnDeviceid"];
39804018
self.hasSeenOmemoDeviceListAfterOwnDeviceid = hasSeenOmemoDeviceListAfterOwnDeviceid.boolValue;
39814019
}
4020+
DDLogError(@"after has seen devicelist after own deviceid...");
39824021

39834022
//debug output
39844023
DDLogVerbose(@"%@ --> readState(saved at %@):\n\tisDoingFullReconnect=%@,\n\tlastHandledInboundStanza=%@,\n\tlastHandledOutboundStanza=%@,\n\tlastOutboundStanza=%@,\n\t#unAckedStanzas=%lu%s,\n\tstreamID=%@,\n\tlastInteractionDate=%@\n\tpersistentIqHandlers=%@\n\tsupportsHttpUpload=%d\n\tpushEnabled=%d\n\tsupportsPubSub=%d\n\tsupportsModernPubSub=%d\n\tsupportsPubSubMax=%d\n\tsupportsBookmarksCompat=%d\n\taccountDiscoDone=%d\n\t_inCatchup=%@\n\tomemo.state=%@\n\thasSeenOmemoDeviceListAfterOwnDeviceid=%@\n\t_cachedStreamFeaturesBeforeAuth=%@\n\t_cachedStreamFeaturesAfterAuth=%@\n",
@@ -4005,10 +4044,12 @@ -(void) realReadState
40054044
bool2str(self->_cachedStreamFeaturesBeforeAuth!=nil),
40064045
bool2str(self->_cachedStreamFeaturesAfterAuth!=nil)
40074046
);
4047+
DDLogError(@"before printing unacked stanzas...");
40084048
if(self.unAckedStanzas)
40094049
for(NSDictionary* dic in self.unAckedStanzas)
40104050
DDLogDebug(@"readState unAckedStanza %@: %@", [dic objectForKey:kQueueID], [dic objectForKey:kStanza]);
40114051
}
4052+
DDLogError(@"after if dic...");
40124053

40134054
//always reset handler and smacksRequestInFlight when loading smacks state
40144055
_smacksAckHandler = [NSMutableArray new];
@@ -4074,14 +4115,32 @@ -(void) initSM3
40744115
self.lastHandledInboundStanza = [NSNumber numberWithInteger:0];
40754116
self.lastHandledOutboundStanza = [NSNumber numberWithInteger:0];
40764117
self.lastOutboundStanza = [NSNumber numberWithInteger:0];
4077-
self.unAckedStanzas = [NSMutableArray new];
4118+
[self replaceUnackedStanzasWith:[NSMutableArray new]];
40784119
self.streamID = nil;
40794120
_smacksAckHandler = [NSMutableArray new];
40804121
DDLogDebug(@"initSM3 done");
40814122
}
40824123
DDLogVerbose(@"After @synchronized of _stateLockObject...");
40834124
}
40844125

4126+
-(NSMutableArray*) replaceUnackedStanzasWith:(NSMutableArray*) newUnackedStanzas
4127+
{
4128+
@synchronized(_stateLockObject) {
4129+
//this might take a long time since it throws away all self.unAckedStanzas and thus calls dealloc on each of them in each nesting level
4130+
//--> move deallocation into a background thread
4131+
NSMutableArray* __block oldUnacked = self.unAckedStanzas;
4132+
self.unAckedStanzas = newUnackedStanzas;
4133+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
4134+
DDLogVerbose(@"Sleeping 500ms before throwing away old unAckedStanzas...");
4135+
[NSThread sleepForTimeInterval:0.500];
4136+
DDLogVerbose(@"Now throwing away old unAckedStanzas...");
4137+
oldUnacked = nil;
4138+
DDLogVerbose(@"All old unAckedStanzas successfully deallocated now...");
4139+
});
4140+
}
4141+
return newUnackedStanzas;
4142+
}
4143+
40854144
-(void) bindResource:(NSString*) resource
40864145
{
40874146
if(resource == nil)

0 commit comments

Comments
 (0)