Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS DefaultHttpEngine StreamingDataDelegate has a thread safety issue #6346

Closed
paxbun opened this issue Jan 10, 2025 · 9 comments
Closed

iOS DefaultHttpEngine StreamingDataDelegate has a thread safety issue #6346

paxbun opened this issue Jan 10, 2025 · 9 comments
Milestone

Comments

@paxbun
Copy link

paxbun commented Jan 10, 2025

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

@martinbonnin
Copy link
Contributor

Hi 👋 Thanks for sending this. Any chance you can try with version 4.1.0? I can't remember anything that would have fixed this but it's worth a try.

@paxbun
Copy link
Author

paxbun commented Jan 10, 2025

I'm also unable to reproduce this problem with the machines I have; I'll let you know if there's any change after upgrading Apollo 4.0.0 to 4.1.0.

@martinbonnin
Copy link
Contributor

martinbonnin commented Jan 10, 2025

Took a look at the code and I believe the issue is still there. Made a fix there: #6348

@paxbun
Copy link
Author

paxbun commented Jan 10, 2025

This is the fix I wanted to apply. Thanks! By the way, can I close this as completed? Would this fix be released in the near future by any chance? If not, I'm going to do some workarounds for this issue in our app.

@martinbonnin
Copy link
Contributor

By the way, can I close this as completed?

Sure thing!

Would this fix be released in the near future by any chance?

We're planning a 4.1.1 release soon-ish. Hopefully next week!

@paxbun paxbun closed this as completed Jan 10, 2025
Copy link
Contributor

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Kotlin usage and allow us to serve you better.

@paxbun
Copy link
Author

paxbun commented Jan 10, 2025

Thanks! Have a nice weekend :)

@BoD BoD added this to the 4.1.1 milestone Jan 10, 2025
@jvanderwee
Copy link
Contributor

Hey @martinbonnin 👋 do you have an update on the 4.1.1. release please?

@martinbonnin
Copy link
Contributor

@jvanderwee We're working on it!

In the meantime, you can always use the previews:

repositories {
  maven {
    url = uri("https://storage.googleapis.com/apollo-previews/m2/")
  }
}

dependencies {
  implementation("com.apollographql.apollo:apollo-runtime:4.1.1-2025.01.21")
}

They have 1 year retention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants