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

Commits on Dec 5, 2016

  1. iOS: Fix dequeueTasks crash in image loader

    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.
    rigdern committed Dec 5, 2016
    Configuration menu
    Copy the full SHA
    b24485a View commit details
    Browse the repository at this point in the history