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: Fix dequeueTasks crash in image loader #11296

Closed

Conversation

rigdern
Copy link
Contributor

@rigdern rigdern commented Dec 5, 2016

This fixes a crash occurring on this line. It was reported in a comment in #10433.

The problem is that task is deallocated at this point and is unsafe to use. Removing it from _pendingTasks dropped its ref count to 0. The ARC docs state that, by default, loop variables in fast enumeration loops are not retained. That's why task's ref count is 0.

It's likely we ran into this bug because the code disobeyed the reverseObjectEnumerator docs which state that "you must not modify the array during enumeration". The default retention policy for fast enumeration seems to assume you follow this.

To fix this bug and avoid other potential pitfalls, the code now follows the docs and _pendingTasks is modified after the loop rather than during it.

Test plan (required)

I couldn't get the reported line to crash because the code never entered this branch in my testing. Consequently, I made a change to RN which introduced a crash and I believe it simulates the conditions of the reported crash. Specifically, in the RCTNetworkTaskFinished case I introduced an access to task after it had been removed from _pendingTasks and I introduced a sleep to make the crash easier to hit. In other words, I changed this code to:

case RCTNetworkTaskFinished:
{
  [self->_pendingTasks removeObject:task];
  sleep(1);
  RCTNetworkTaskStatus status __attribute__ ((unused)) = task.status;
  self->_activeTasks--;
  break;
}

Before my fix, this crashed consistently using https://github.com/rigdern/RNImageRepro. After my fix, it did not crash.

Additionally, @SylviaRu stated this change avoids the crash. This statement is consistent with my understanding of the cause of the bug which adds confidence to this PR.

This fixes a crash occurring [on this line](https://github.com/facebook/react-native/blob/f9f32eb426b5385e199ef6e1d2b610dfe20e60e7/Libraries/Image/RCTImageLoader.m#L253). It was reported in facebook#10433.

The problem is that `task` is deallocated at this point and is unsafe to use. Removing it from `_pendingTasks` dropped its ref count to 0. [The ARC docs](http://clang.llvm.org/docs/AutomaticReferenceCounting.html#fast-enumeration-iteration-variables) state that, by default, loop variables in fast enumeration loops are not retained. That's why `task`'s ref count is 0.

It's likely we ran into this bug because the code disobeyed the [reverseObjectEnumerator docs](https://developer.apple.com/reference/foundation/nsarray/1415734-reverseobjectenumerator) which state that "you must not modify the array during enumeration". The default retention policy for fast enumeration seems to assume you follow this.

To fix this bug and avoid other potential pitfalls, the code now follow the docs and `_pendingTasks` is modified after the loop rather than during it.

**Test plan (required)**

I couldn't get the reported line to crash because the code [never entered this branch](https://github.com/facebook/react-native/blob/f9f32eb426b5385e199ef6e1d2b610dfe20e60e7/Libraries/Image/RCTImageLoader.m#L250-L253). Consequently, I made a change to RN which introduced a crash and I believe it simulates the conditions of the reported crash. Specifically, in the `RCTNetworkTaskFinished` case I introduced an access to `task` after it had been removed from `_pendingTasks` and I introduced a `sleep` to make the crash easier to hit. In other words, I changed [this code](https://github.com/facebook/react-native/blob/f9f32eb426b5385e199ef6e1d2b610dfe20e60e7/Libraries/Image/RCTImageLoader.m#L241-L244) to:

```
case RCTNetworkTaskFinished:
{
  [self->_pendingTasks removeObject:task];
  sleep(1);
  RCTNetworkTaskStatus status __attribute__ ((unused)) = task.status;
  self->_activeTasks--;
  break;
}
```

Before my fix, this crashed consistently using https://github.com/rigdern/RNImageRepro. After my fix, it did not crash.
@facebook-github-bot
Copy link
Contributor

By analyzing the blame information on this pull request, we identified @javache and @skatpgusskat to be potential reviewers.

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Dec 5, 2016
@javache
Copy link
Member

javache commented Dec 5, 2016

@facebook-github-bot shipit

@facebook-github-bot facebook-github-bot added the Import Started This pull request has been imported. This does not imply the PR has been approved. label Dec 5, 2016
@facebook-github-bot
Copy link
Contributor

@javache has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

robclouth pushed a commit to robclouth/react-native that referenced this pull request Dec 7, 2016
Summary:
This fixes a crash occurring [on this line](https://github.com/facebook/react-native/blob/f9f32eb426b5385e199ef6e1d2b610dfe20e60e7/Libraries/Image/RCTImageLoader.m#L253). It was reported in a comment in facebook#10433.

The problem is that `task` is deallocated at this point and is unsafe to use. Removing it from `_pendingTasks` dropped its ref count to 0. [The ARC docs](http://clang.llvm.org/docs/AutomaticReferenceCounting.html#fast-enumeration-iteration-variables) state that, by default, loop variables in fast enumeration loops are not retained. That's why `task`'s ref count is 0.

It's likely we ran into this bug because the code disobeyed the [reverseObjectEnumerator docs](https://developer.apple.com/reference/foundation/nsarray/1415734-reverseobjectenumerator) which state that "you must not modify the array during enumeration". The default retention policy for fast enumeration seems to assume you follow this.

To fix this bug and avoid other potential pitfalls, the code now follows the docs and `_pendingTa
Closes facebook#11296

Differential Revision: D4277167

Pulled By: javache

fbshipit-source-id: 1211b32935bab7f4080dc00b88d85348786e859a
mkonicek pushed a commit that referenced this pull request Dec 12, 2016
Summary:
This fixes a crash occurring [on this line](https://github.com/facebook/react-native/blob/f9f32eb426b5385e199ef6e1d2b610dfe20e60e7/Libraries/Image/RCTImageLoader.m#L253). It was reported in a comment in #10433.

The problem is that `task` is deallocated at this point and is unsafe to use. Removing it from `_pendingTasks` dropped its ref count to 0. [The ARC docs](http://clang.llvm.org/docs/AutomaticReferenceCounting.html#fast-enumeration-iteration-variables) state that, by default, loop variables in fast enumeration loops are not retained. That's why `task`'s ref count is 0.

It's likely we ran into this bug because the code disobeyed the [reverseObjectEnumerator docs](https://developer.apple.com/reference/foundation/nsarray/1415734-reverseobjectenumerator) which state that "you must not modify the array during enumeration". The default retention policy for fast enumeration seems to assume you follow this.

To fix this bug and avoid other potential pitfalls, the code now follows the docs and `_pendingTa
Closes #11296

Differential Revision: D4277167

Pulled By: javache

fbshipit-source-id: 1211b32935bab7f4080dc00b88d85348786e859a
gabceb pushed a commit to tes/react-native that referenced this pull request Dec 19, 2016
Summary:
This fixes a crash occurring [on this line](https://github.com/facebook/react-native/blob/f9f32eb426b5385e199ef6e1d2b610dfe20e60e7/Libraries/Image/RCTImageLoader.m#L253). It was reported in a comment in facebook#10433.

The problem is that `task` is deallocated at this point and is unsafe to use. Removing it from `_pendingTasks` dropped its ref count to 0. [The ARC docs](http://clang.llvm.org/docs/AutomaticReferenceCounting.html#fast-enumeration-iteration-variables) state that, by default, loop variables in fast enumeration loops are not retained. That's why `task`'s ref count is 0.

It's likely we ran into this bug because the code disobeyed the [reverseObjectEnumerator docs](https://developer.apple.com/reference/foundation/nsarray/1415734-reverseobjectenumerator) which state that "you must not modify the array during enumeration". The default retention policy for fast enumeration seems to assume you follow this.

To fix this bug and avoid other potential pitfalls, the code now follows the docs and `_pendingTa
Closes facebook#11296

Differential Revision: D4277167

Pulled By: javache

fbshipit-source-id: 1211b32935bab7f4080dc00b88d85348786e859a
ide pushed a commit to expo/react-native that referenced this pull request Dec 20, 2016
Summary:
This fixes a crash occurring [on this line](https://github.com/facebook/react-native/blob/f9f32eb426b5385e199ef6e1d2b610dfe20e60e7/Libraries/Image/RCTImageLoader.m#L253). It was reported in a comment in facebook#10433.

The problem is that `task` is deallocated at this point and is unsafe to use. Removing it from `_pendingTasks` dropped its ref count to 0. [The ARC docs](http://clang.llvm.org/docs/AutomaticReferenceCounting.html#fast-enumeration-iteration-variables) state that, by default, loop variables in fast enumeration loops are not retained. That's why `task`'s ref count is 0.

It's likely we ran into this bug because the code disobeyed the [reverseObjectEnumerator docs](https://developer.apple.com/reference/foundation/nsarray/1415734-reverseobjectenumerator) which state that "you must not modify the array during enumeration". The default retention policy for fast enumeration seems to assume you follow this.

To fix this bug and avoid other potential pitfalls, the code now follows the docs and `_pendingTa
Closes facebook#11296

Differential Revision: D4277167

Pulled By: javache

fbshipit-source-id: 1211b32935bab7f4080dc00b88d85348786e859a
ide pushed a commit to expo/react-native that referenced this pull request Dec 20, 2016
Summary:
This fixes a crash occurring [on this line](https://github.com/facebook/react-native/blob/f9f32eb426b5385e199ef6e1d2b610dfe20e60e7/Libraries/Image/RCTImageLoader.m#L253). It was reported in a comment in facebook#10433.

The problem is that `task` is deallocated at this point and is unsafe to use. Removing it from `_pendingTasks` dropped its ref count to 0. [The ARC docs](http://clang.llvm.org/docs/AutomaticReferenceCounting.html#fast-enumeration-iteration-variables) state that, by default, loop variables in fast enumeration loops are not retained. That's why `task`'s ref count is 0.

It's likely we ran into this bug because the code disobeyed the [reverseObjectEnumerator docs](https://developer.apple.com/reference/foundation/nsarray/1415734-reverseobjectenumerator) which state that "you must not modify the array during enumeration". The default retention policy for fast enumeration seems to assume you follow this.

To fix this bug and avoid other potential pitfalls, the code now follows the docs and `_pendingTa
Closes facebook#11296

Differential Revision: D4277167

Pulled By: javache

fbshipit-source-id: 1211b32935bab7f4080dc00b88d85348786e859a
@rigdern rigdern deleted the rigdern/iosDequeueTasksCrash branch December 20, 2016 20:48
ide pushed a commit to expo/react-native that referenced this pull request Dec 29, 2016
Summary:
This fixes a crash occurring [on this line](https://github.com/facebook/react-native/blob/f9f32eb426b5385e199ef6e1d2b610dfe20e60e7/Libraries/Image/RCTImageLoader.m#L253). It was reported in a comment in facebook#10433.

The problem is that `task` is deallocated at this point and is unsafe to use. Removing it from `_pendingTasks` dropped its ref count to 0. [The ARC docs](http://clang.llvm.org/docs/AutomaticReferenceCounting.html#fast-enumeration-iteration-variables) state that, by default, loop variables in fast enumeration loops are not retained. That's why `task`'s ref count is 0.

It's likely we ran into this bug because the code disobeyed the [reverseObjectEnumerator docs](https://developer.apple.com/reference/foundation/nsarray/1415734-reverseobjectenumerator) which state that "you must not modify the array during enumeration". The default retention policy for fast enumeration seems to assume you follow this.

To fix this bug and avoid other potential pitfalls, the code now follows the docs and `_pendingTa
Closes facebook#11296

Differential Revision: D4277167

Pulled By: javache

fbshipit-source-id: 1211b32935bab7f4080dc00b88d85348786e859a
DanielMSchmidt pushed a commit to DanielMSchmidt/react-native that referenced this pull request Jan 4, 2017
Summary:
This fixes a crash occurring [on this line](https://github.com/facebook/react-native/blob/f9f32eb426b5385e199ef6e1d2b610dfe20e60e7/Libraries/Image/RCTImageLoader.m#L253). It was reported in a comment in facebook#10433.

The problem is that `task` is deallocated at this point and is unsafe to use. Removing it from `_pendingTasks` dropped its ref count to 0. [The ARC docs](http://clang.llvm.org/docs/AutomaticReferenceCounting.html#fast-enumeration-iteration-variables) state that, by default, loop variables in fast enumeration loops are not retained. That's why `task`'s ref count is 0.

It's likely we ran into this bug because the code disobeyed the [reverseObjectEnumerator docs](https://developer.apple.com/reference/foundation/nsarray/1415734-reverseobjectenumerator) which state that "you must not modify the array during enumeration". The default retention policy for fast enumeration seems to assume you follow this.

To fix this bug and avoid other potential pitfalls, the code now follows the docs and `_pendingTa
Closes facebook#11296

Differential Revision: D4277167

Pulled By: javache

fbshipit-source-id: 1211b32935bab7f4080dc00b88d85348786e859a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Import Started This pull request has been imported. This does not imply the PR has been approved. p: Microsoft Partner: Microsoft Partner
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants