Skip to content

Commit f115b3a

Browse files
committed
fix(call): fast-path offer and line delivery to unblock push-answer mutation queue deadlock
__onMutationPerformAnswer (sequential mutation queue) awaits stream.firstWhere(incomingOffer != null) while holding the queue slot. __onMutationSignalingIncoming — which stores the offer and line in state — is queued behind it and cannot run: deadlock, resolved only by 10 s timeout. Fix: in __onCallSignalingEventIncoming (_CallSignalingEvent queue, independent of the mutation queue), emit offer and line directly to BLoC state when the call is in a push-answer waiting status and has no offer yet. This immediately satisfies stream.firstWhere without touching the mutation queue and ensures AcceptRequest is sent with the correct SIP line.
1 parent 3ee90ce commit f115b3a

1 file changed

Lines changed: 22 additions & 0 deletions

File tree

lib/features/call/bloc/call_bloc.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,28 @@ class CallBloc extends Bloc<CallEvent, CallState> with WidgetsBindingObserver im
940940
_logger.infoPretty(event.jsep?.sdp, tag: '__onCallSignalingEventIncoming');
941941

942942
final handle = CallkeepHandle.number(event.caller);
943+
944+
if (event.jsep != null) {
945+
final waitingCall = state.retrieveActiveCall(event.callId);
946+
if (waitingCall != null && waitingCall.incomingOffer == null) {
947+
final s = waitingCall.processingStatus;
948+
if (s == CallProcessingStatus.incomingFromPush ||
949+
s == CallProcessingStatus.incomingSubmittedAnswer ||
950+
s == CallProcessingStatus.incomingPerformingStarted) {
951+
_logger.info(
952+
'__onCallSignalingEventIncoming: fast-pathing offer to awaiting push call — '
953+
'callId=${event.callId} status=$s',
954+
);
955+
emit(
956+
state.copyWithMappedActiveCall(
957+
event.callId,
958+
(call) => call.copyWith(incomingOffer: event.jsep, line: event.line),
959+
),
960+
);
961+
}
962+
}
963+
}
964+
943965
final contactName = await contactNameResolver.resolveWithNumber(handle.value);
944966
final displayName = contactName ?? (event.callerDisplayName?.isEmpty == true ? null : event.callerDisplayName);
945967

0 commit comments

Comments
 (0)