Skip to content

iOS DefaultHttpEngine StreamingDataDelegate has a thread safety issue #6346

@paxbun

Description

@paxbun

Version

4.0.0-rc.1

Summary

With HttpInterceptor, when invoking Apollo from multiple threads (e.g. using MultithreadedDispatchers), HashMap.put throws ArrayIndexOutOfBoundsException or IllegalStateException, which is called by StreamingDataDelegate.registerHandlerForTask. In our app on iOS 18, about 10% of the users experience this problem.

Steps to reproduce the behavior

  1. Add an HttpInterceptor when building a ApolloClient.
addHttpInterceptor(object : HttpInterceptor {
    override suspend fun intercept(
        request: HttpRequest, chain: HttpInterceptorChain
    ): HttpResponse {
        val token = try {
            authenticationService.acquireToken()
        } catch (ex: CancellationException) {
            throw ex
        } catch (e: Exception) {
            null
        }
        return chain.proceed(
            when {
                token == null -> request
                else -> request
                    .newBuilder()
                    .addHeader("Authorization", "Bearer $token")
                    .build()
            },
        )
    }
})
  1. Invoke multiple Apollo queries or mutations in a multithreaded coroutine context.
  2. You'll experience an exception thrown from HashMap randomly.

Logs

ArrayIndexOutOfBoundsException stacktrace

image

IllegalStateException stacktrace

image

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions