Skip to content

EXC_BAD_ACCESS to store from interceptAsync #3500

@lhunath

Description

@lhunath

Summary

The application crashed with the following backtrace:

  * frame #0: 0x0000000101b0641c Server`CacheReadInterceptor.fetchFromCache<ActivitiesServer.DaysWithActivitiesQuery>(request=0x000060000370b540, chain=0x00006000026ce040, completion=0x101b06b6c) at CacheReadInterceptor.swift:121:18
    frame #1: 0x0000000101b05e5c Server`CacheReadInterceptor.interceptAsync<ActivitiesServer.DaysWithActivitiesQuery>(chain=0x00006000026ce040, request=0x000060000370b540, response=nil, completion=0x101af9fd0) at CacheReadInterceptor.swift:72:16
    frame #2: 0x0000000101b06e20 Server`protocol witness for ApolloInterceptor.interceptAsync<A>(chain:request:response:completion:) in conformance CacheReadInterceptor at <compiler-generated>:0
    frame #3: 0x0000000101b4dd8c Server`InterceptorRequestChain.proceedAsync<ActivitiesServer.DaysWithActivitiesQuery>(interceptorIndex=2, request=0x000060000370b540, response=nil, completion=0x101af9fd0) at InterceptorRequestChain.swift:156:19
    frame #4: 0x0000000101b4e14c Server`InterceptorRequestChain.proceedAsync<ActivitiesServer.DaysWithActivitiesQuery>(request=0x000060000370b540, response=nil, interceptor=(payload_data_0 = 0x0000600000df6e20 -> 0x0000000101bccea0 type metadata for Apollo.MaxRetryInterceptor, payload_data_1 = 0x0000000194c48824 libswiftCore.dylib`Swift.RandomAccessCollection< where τ_0_0.Index: Swift.Strideable, τ_0_0.Indices == Swift.Range<τ_0_0.Index>, τ_0_0.Index.Stride == Swift.Int>.indices.getter : Swift.Range<τ_0_0.Index> + 564, payload_data_2 = 0x0000000000000000, metadata = Any.Type, wtable = 0x0000000101bc4c40 Server`protocol witness table for Apollo.MaxRetryInterceptor : Apollo.ApolloInterceptor in Apollo), completion=0x101af9fd0) at InterceptorRequestChain.swift:133:5
    frame #5: 0x0000000101b4f4e8 Server`protocol witness for RequestChain.proceedAsync<A>(request:response:interceptor:completion:) in conformance InterceptorRequestChain at <compiler-generated>:0
    frame #6: 0x0000000101b580d4 Server`MaxRetryInterceptor.interceptAsync<ActivitiesServer.DaysWithActivitiesQuery>(chain=0x00006000026ce040, request=0x000060000370b540, response=nil, completion=0x101af9fd0) at MaxRetryInterceptor.swift:54:11
    frame #7: 0x0000000101b58324 Server`protocol witness for ApolloInterceptor.interceptAsync<A>(chain:request:response:completion:) in conformance MaxRetryInterceptor at <compiler-generated>:0
    frame #8: 0x0000000101b4dd8c Server`InterceptorRequestChain.proceedAsync<ActivitiesServer.DaysWithActivitiesQuery>(interceptorIndex=1, request=0x000060000370b540, response=nil, completion=0x101af9fd0) at InterceptorRequestChain.swift:156:19
    frame #9: 0x0000000101b4e14c Server`InterceptorRequestChain.proceedAsync<ActivitiesServer.DaysWithActivitiesQuery>(request=0x000060000370b540, response=nil, interceptor=0x0000600000df2f70, completion=0x101af9fd0) at InterceptorRequestChain.swift:133:5
    frame #10: 0x0000000101b4f4e8 Server`protocol witness for RequestChain.proceedAsync<A>(request:response:interceptor:completion:) in conformance InterceptorRequestChain at <compiler-generated>:0
    frame #11: 0x0000000101af36d4 Server`CoreAuthenticatingInterceptor.interceptAsync<ActivitiesServer.DaysWithActivitiesQuery>(chain=0x00006000026ce040, request=0x000060000370b540, response=nil, completion=0x101af9fd0) at ServerInteractor.swift:88:15
    frame #12: 0x0000000101af4068 Server`protocol witness for ApolloInterceptor.interceptAsync<A>(chain:request:response:completion:) in conformance CoreAuthenticatingInterceptor at <compiler-generated>:0
    frame #13: 0x0000000101b4d21c Server`InterceptorRequestChain.kickoff<ActivitiesServer.DaysWithActivitiesQuery>(request=0x000060000370b540, completion=0x101af9fd0) at InterceptorRequestChain.swift:76:22
    frame #14: 0x0000000101b4f4c0 Server`protocol witness for RequestChain.kickoff<A>(request:completion:) in conformance InterceptorRequestChain at <compiler-generated>:0
    frame #15: 0x0000000101b6e2d4 Server`RequestChainNetworkTransport.send<ActivitiesServer.DaysWithActivitiesQuery>(operation=(organizationId = unable to read data, memberId = unable to read data, timeZone = unable to read data), cachePolicy=returnCacheDataElseFetch, contextIdentifier=nil, context=nil, callbackQueue=0x0000000101e5cdc0, completionHandler=0x101af9fd0) at RequestChainNetworkTransport.swift:139:11
    frame #16: 0x0000000101b6e5a8 Server`protocol witness for NetworkTransport.send<A>(operation:cachePolicy:contextIdentifier:context:callbackQueue:completionHandler:) in conformance RequestChainNetworkTransport at <compiler-generated>:0
    frame #17: 0x0000000101af9e40 Server`ApolloClient.fetch<ActivitiesServer.DaysWithActivitiesQuery>(query=(organizationId = unable to read data, memberId = unable to read data, timeZone = unable to read data), cachePolicy=returnCacheDataElseFetch, contextIdentifier=nil, context=nil, queue=0x0000000101e5cdc0, resultHandler=0x0000000101af4a90 Server`partial apply forwarder for closure #1 (Swift.Result<Apollo.GraphQLResult<A.Data>, Swift.Error>) -> () in closure #1 () async -> Apollo.Cancellable in closure #1 ((Swift.Result<A.Data, Swift.Error>) -> ()) -> () in Server.ServerInteractor.publisher<A where A: ApolloAPI.GraphQLQuery>(query: A) -> Combine.AnyPublisher<A.Data, Swift.Error> at <compiler-generated>) at ApolloClient.swift:88:34

Upon inspection, we find at frame #0 (CacheReadInterceptor.swift:121), self.store has been deinitialized:

(lldb) p self.store
(Apollo.ApolloStore) 0x0000600000dd24c0 {
  cache = (object = 0x0000000000000000, wtable = 0x0000000000000000)
  queue = <uninitialized>
  subscribers = <uninitialized> {
    _buffer = {
      _storage = (rawValue = 0x0000000000000000)
    }
  }
}

While at frame #17 (ApolloClient.swift:88), self.store is a different object:

(lldb) p self.store
(Apollo.ApolloStore) 0x0000600000dd2c10 {
  cache = 0x000060000045c0a0 {
    records = {
      storage = 0 key/value pairs {}
    }
  }
  queue = 0x0000600002d10a80 {
    baseOS_dispatch_queue@0 = {
      baseOS_dispatch_object@0 = {
        baseOS_object@0 = {
          baseNSObject@0 = {
            isa = OS_dispatch_queue_concurrent{...}
          }
        }
      }
    }
  }
  subscribers = 0 values {}
}

Note that frame #11 (ServerInteractor.swift:88) involves a custom interceptor:

private class CoreAuthenticatingInterceptor: ApolloInterceptor {
    public var id: String = UUID().uuidString

    func interceptAsync<O: GraphQLOperation>(
        chain: RequestChain, request: HTTPRequest<O>, response: HTTPResponse<O>?,
        completion: @escaping (Result<GraphQLResult<O.Data>, Error>) -> Void
    ) {
        if let signature = self.coreInteractor.signed(api: "/v2/graphql", method: "POST") {
            signature.url.flatMap { request.graphQLEndpoint = $0 }
            signature.allHTTPHeaderFields?.forEach {
                request.addHeader(name: $0, value: $1)
            }
        }

        chain.proceedAsync(request: request, response: response, interceptor: self, completion: completion)
    }

    private lazy var coreInteractor: CoreInteractor = Registry.shared.resolve()
}

Version

1.16.0

Steps to reproduce the behavior

Unclear

Logs

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions