Skip to content
This repository has been archived by the owner on Jan 28, 2024. It is now read-only.

Reuse Blocks in ObjCBlock.fromFunction #477

Closed
wants to merge 5 commits into from
Closed

Conversation

liamappelbe
Copy link
Contributor

@liamappelbe liamappelbe commented Oct 19, 2022

When ObjCBlock.fromFunction is passed in the same function multiple times, return a new ObjCBlock that wraps the same underlying block struct. Explicitly retain (increase ref count) of the block struct in this case. This helps reduce the leak caused by dart-lang/native#204 by reducing the number of blocks created if the user accidentally creates many blocks from the same function.

This is accomplished by sticking the block struct pointer in an Expando (_funcToBlock), with the Dart function as the key.

I also tried sticking the ObjCBlock directly in _funcToBlock, which was simpler and cleaner, but this caused the ObjCBlock to never be GC'd, because the Dart function is reachable via the _ObjCBlock_closureRegistry. We can try refactoring this to put the ObjCBlock in the _funcToBlock once dart-lang/native#204 is fixed.

Fixes dart-lang/native#226

$exceptionalReturn).cast(), $registerClosure(fn)), lib);
$exceptionalReturn).cast(), $registerClosure(fn));
_funcToBlock[fn] = newBlock;
return $name._(newBlock, lib);

Choose a reason for hiding this comment

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

We don't increase refcount for newBlock here.

What happens if the underlying obj-c block is de-rereferenced and freed while still being in the expando map? If one creates another block for same closure, we have a use-after-free, don't we?

I'll comment more on the github issue

Choose a reason for hiding this comment

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

I guess the assumption is that the dart wrapper will keep a refcount as long as it's alive?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, the Dart wrapper always holds one reference. In all the other cases where we construct the wrapper function, we're using a block pointer from Block_copy, which already has an incremented ref count.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

Successfully merging this pull request may close these issues.

ObjCBlock.fromFunction should return same block for same function
2 participants