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

Fixed memory leak by way of accidental retain on implicit self #9329

Merged
merged 8 commits into from
Jun 28, 2019

Conversation

gaaclarke
Copy link
Member

Related issue: flutter/flutter#26007

One potential problem with this change is that it may break clients code because they might have been relying on the fact that there is a retain cycle that keeps channels alive instead of keeping them alive themselves. We even actively encourage not taking care of channels correctly like in the following doc: https://flutter.dev/docs/development/platform-integration/platform-channels#step-4a-add-an-ios-platform-specific-implementation-using-objective-c

After this fix there will be no need to fiddle with the channel in order to get the FlutterViewController to dealloc, as seen in this gist: https://gist.github.com/gaaclarke/aa1f2512bb41c0972e381d06f610c4a0#file-gistfile1-txt-L50

Copy link
Contributor

@dnfield dnfield left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM. When it lands in the engine, we should add a test to ios_add2app in the framework to catch it.

Alternatively, we should add functionality in the engine to run unit tests for this kind of thing on Objective C code (that's long been desired).

@gaaclarke
Copy link
Member Author

gaaclarke commented Jun 14, 2019

We can't check this in as it currently stands yet because it will break plugins. Authors of plugins are assuming that channels won't get deleted. Here is example code from the connectivity plugin:

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
  FLTConnectivityPlugin* instance = [[FLTConnectivityPlugin alloc] init];

  FlutterMethodChannel* channel =
      [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/connectivity"
                                  binaryMessenger:[registrar messenger]];
  [registrar addMethodCallDelegate:instance channel:channel];

  FlutterEventChannel* streamChannel =
      [FlutterEventChannel eventChannelWithName:@"plugins.flutter.io/connectivity_status"
                                binaryMessenger:[registrar messenger]];
  [streamChannel setStreamHandler:instance];
}

@cbracken
Copy link
Member

@gaaclarke is the plan to eventually land this or would you like to close it then land the larger API refactor you've proposed, which'll involve a breaking change?

@xster
Copy link
Member

xster commented Jun 24, 2019

I think #9419 is the replacement of this

@gaaclarke
Copy link
Member Author

After #9419 this is much lower priority. I'd like to commit this only with the larger change. I was leaving it out there until we addressed the other concerns. I didn't realize it was going to take so long. Do you want me to close it? Maybe I can just flag it WIP?

@gaaclarke gaaclarke added the Work in progress (WIP) Not ready (yet) for review! label Jun 24, 2019
@gaaclarke
Copy link
Member Author

I had a chat with Amir and it seems that this might work without further change. It's a bit unintuitive but you don't need a channel in order for communication to work, so the deleting of the channels might not be a big deal because the binary messenger will hold onto the necessary objects. This will require a bit more testing.

@xster
Copy link
Member

xster commented Jun 26, 2019

Interesting. Can you describe what the needed linkage (that's still held after the channel's gone) is?

@gaaclarke
Copy link
Member Author

The binary messenger holds on to all the required state by-way-of a lambda.

[_messenger setMessageHandlerOnChannel:_name binaryMessageHandler:messageHandler];

I don't like the way this is setup, I think it is confusing that you don't need a channel in order to communicate but that is also how it is setup on Android.

@gaaclarke
Copy link
Member Author

I was able to test this and Amir was right. The channels don't need to be in memory to be communicated upon, just like in Android. This change should be safe.

@gaaclarke gaaclarke removed the Work in progress (WIP) Not ready (yet) for review! label Jun 27, 2019
deallocated to match behaviour of other channels.
@gaaclarke
Copy link
Member Author

I had to change the original PR to make sure that the FlutterEventChannel will function beyond being deallocated like the other channels to match the functionality that Amir wants.

@gaaclarke gaaclarke requested a review from amirh June 27, 2019 22:57
Copy link
Contributor

@amirh amirh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@gaaclarke gaaclarke merged commit 7a0bbf9 into flutter:master Jun 28, 2019
@a-siva
Copy link
Contributor

a-siva commented Jun 28, 2019

The engine buildbot turned red after this commit, any ideas?

engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jul 1, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jul 1, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants