RxSwift: Heap corruption and Attempt to use unknown class

Short description of the issue: RxSwift is crashing with Attempt to use unknown class at 0x265a091a or

*** Incorrect guard value: 10770528256
RxSwiftIssue(25384,0x100cbef80) malloc: *** set a breakpoint in malloc_error_break to debug

With Xcode 10.2.1 and RxSwift 4.5.0 installed through cocoapods or source files directly, not carthage.

It doesn’t reproduces with Xcode 10.1

It is required to have a prebuilt binary in your project, which was build with release configuration that uses RxSwift as dependency, if you do not have this, it won’t reproduce.

Embed the prebuilt framework in your project. Install RxSwift (source files, or cocoapods)

Use the functionality of the prebuild binary framework that uses RxSwift.

Expected outcome: The functionality works as expected and you do not have any crash.

What actually happens: RxSwift crashes with Attempt to use unknown class at 0x265a091a or Heap corruption.

Self contained code example that reproduces the issue: I attached a sample project that reproduces the issue. As well as the code for the prebuilt binary.

Just download the sample project Build the sample framework.

cd SampleFramework
carthage bootstrap --platform iOS
open SampleFramework.xcodeproj

Build the scheme SampleProjectAggregate This scheme will create the prebuilt binary that uses RxSwift at SampleFramework/build

Setup RxSwift sample project

cd ../RxSwiftIssue/
pod install
open RxSwiftIssue.xcworkspace

Make sure you embed SampleFramework.framework in RxSwiftIssue app.

Run the RxSwiftIssue app Tap start on the first screen. Tap start on the second screen. And you should have a crash, if not, retry by tapping stop and start.

RxSwiftHeapCorruption.zip

RxSwift/RxCocoa/RxBlocking/RxTest version/commit

cce95dd7 Krunoslav Zaher. Fix TSAN issues. tag: 4.5.0

Platform/Environment

  • iOS
  • macOS
  • tvOS
  • watchOS
  • playgrounds

How easy is to reproduce? (chances of successful reproduce after running the self contained code)

  • easy, 100% repro
  • sometimes, 10%-100%
  • hard, 2% - 10%
  • extremely hard, %0 - 2%

Xcode version:

  10.2.1

Installation method:

  • CocoaPods
  • Carthage
  • Git submodules

I have multiple versions of Xcode installed: (so we can know if this is a potential cause of your issue)

  • yes (which ones) Xcode 10.1.
  • no

Level of RxSwift knowledge: (this is so we can understand your level of knowledge and formulate the response in an appropriate manner)

  • just starting
  • I have a small code base
  • I have a significant code base

###### Workaround
If you replace the occurrence of `#if DEBUG` with a different flag which is not present when you build for debug, for example replace it with `#if FORCE_DEBUG`, you won't get the crash.
To get the crash you just to enable the code for `fileprivate let _synchronizationTracker = SynchronizationTracker()` in `PublishSubject.swift` and `Rx.swift`.

Carthage builds the project with configuration Release, therefore that code is not part of the framework that carthage produces.
But when you build it with cocoapods or as a submodule it will have the DEBUG flag.
Wich enables the `SynchronizationTracker` for the subjects.
Which I think causes the crash.

If you will use the SampleProject.framework sources directly in RxSwiftIssue project instead of the prebuilt binaries, it won't trigger the crash.

Our use case is a bit more complex, we distribute prebuilt binaries through cocoapods, that have as dependency RxSwift 4.5. Still the SampleProject is more or less the same idea.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 8
  • Comments: 23 (5 by maintainers)

Most upvoted comments

We pull RxSwift as a dependency via CocoaPods and I ran into this exact same issue. As a workaround, I added the following snippet in our Podfile:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    if target.name == "RxSwift"
      target.build_configurations.each do |config|
        if config.name == "Debug"
          config.build_settings['SWIFT_ACTIVE_COMPILATION_CONDITIONS'] = []
        end
      end
    end
  end
end

Still though, someone please fix this!

@DamienBallenghien we are using a CI that builds our SDK based on a hook. Some of our frameworks have RxSwift as a dependency in Link Binary with Frameworks. After everything is built, we have a script that copies RxSwift together with our frameworks. We release our SDK through cocoapods specs and we add RxSwift in the subspesc.vendored_frameworks together with our frameworks.

We are still including RxSwift as pre-build library in our SDK.

you can replace DEBUG by anything else, the idea is to disable the rule.

to “fix” it, when we build a debug build on our CI we do:

  • pod install
  • shell script that replaces every occurrences of #if DEBUG by #if FORCE_DEBUG in files AsyncSubject.swift, PublishSubject.swift, BehaviorSubject.swift, ReplaySubject.swift, Create.swift, Sink.swift
  • build

We are not using Swift 5.1.2 yet, I don’t know if our project would work without the script.

In this case the issues are coming from this class final class SynchronizationTracker, which is available when you build for debug. Mainly when it is used in Subjects, like in PublishSubject.swift

    #if DEBUG
        fileprivate let _synchronizationTracker = SynchronizationTracker()
    #endif

In order to make RxSwift not to crash, I just made sure that this is not available when I build for debug. I only changed the flag, from #if DEBUG to #if FORCE_DEBUG, I do not understand entirely why this is causing the crash, most of the times is crashing when self._lock.lock() is called, it crashes with Thread 1: EXC_BAD_ACCESS (code=1, address=0x6000617ac2c0), or SIGABRT, and the console message Attempt to use unknown class or Heap corruption.

I do not know what is the purpose of _synchronizationTracker and why it is crashing from it, I was hopping that you guys might have an idea. Screenshot 2019-05-14 at 14 15 23