mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-22 01:40:07 +01:00
Fix group state loss during concurrent updates.
Storage sync and a message process can both attempt to create a group at the same time. Message processing caches the local group state and performs networking which allows the cached state to become stale. The state was being used to decide to call create instead of update and the create would fail silently as the group record already exists. This would cause state to not be persisted and result in odd double events.
This commit is contained in:
@@ -294,10 +294,15 @@ final class GroupManagerV2 {
|
||||
throw new GroupChangeFailedException(e);
|
||||
}
|
||||
|
||||
GroupMasterKey masterKey = groupSecretParams.getMasterKey();
|
||||
GroupId.V2 groupId = groupDatabase.create(masterKey, decryptedGroup);
|
||||
RecipientId groupRecipientId = SignalDatabase.recipients().getOrInsertFromGroupId(groupId);
|
||||
Recipient groupRecipient = Recipient.resolved(groupRecipientId);
|
||||
GroupMasterKey masterKey = groupSecretParams.getMasterKey();
|
||||
GroupId.V2 groupId = groupDatabase.create(masterKey, decryptedGroup);
|
||||
|
||||
if (groupId == null) {
|
||||
throw new GroupChangeFailedException("Unable to create group, group already exists");
|
||||
}
|
||||
|
||||
RecipientId groupRecipientId = SignalDatabase.recipients().getOrInsertFromGroupId(groupId);
|
||||
Recipient groupRecipient = Recipient.resolved(groupRecipientId);
|
||||
|
||||
AvatarHelper.setAvatar(context, groupRecipientId, avatar != null ? new ByteArrayInputStream(avatar) : null);
|
||||
groupDatabase.onAvatarUpdated(groupId, avatar != null);
|
||||
@@ -946,8 +951,20 @@ final class GroupManagerV2 {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
groupDatabase.create(groupMasterKey, decryptedGroup);
|
||||
Log.i(TAG, "Created local group with placeholder");
|
||||
GroupId.V2 groupId = groupDatabase.create(groupMasterKey, decryptedGroup);
|
||||
if (groupId != null) {
|
||||
Log.i(TAG, "Created local group with placeholder");
|
||||
} else {
|
||||
Log.i(TAG, "Create placeholder failed, group suddenly present locally, attempting to apply change");
|
||||
if (decryptedChange != null) {
|
||||
try {
|
||||
groupsV2StateProcessor.forGroup(SignalStore.account().getServiceIds(), groupMasterKey)
|
||||
.updateLocalGroupToRevision(decryptedChange.getRevision(), System.currentTimeMillis(), decryptedChange);
|
||||
} catch (GroupNotAMemberException e) {
|
||||
Log.w(TAG, "Unable to apply join change to existing group", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RecipientId groupRecipientId = SignalDatabase.recipients().getOrInsertFromGroupId(groupId);
|
||||
|
||||
@@ -21,11 +21,11 @@ import org.signal.storageservice.protos.groups.local.DecryptedPendingMember;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.MessageTable;
|
||||
import org.thoughtcrime.securesms.database.RecipientTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadTable;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupDoesNotExistException;
|
||||
@@ -554,7 +554,11 @@ public class GroupsV2StateProcessor {
|
||||
boolean needsAvatarFetch;
|
||||
|
||||
if (inputGroupState.getLocalState() == null) {
|
||||
groupDatabase.create(masterKey, newLocalState);
|
||||
GroupId.V2 groupId = groupDatabase.create(masterKey, newLocalState);
|
||||
if (groupId == null) {
|
||||
Log.w(TAG, "Group create failed, trying to update");
|
||||
groupDatabase.update(masterKey, newLocalState);
|
||||
}
|
||||
needsAvatarFetch = !TextUtils.isEmpty(newLocalState.getAvatar());
|
||||
} else {
|
||||
groupDatabase.update(masterKey, newLocalState);
|
||||
|
||||
Reference in New Issue
Block a user