maps icon indicating copy to clipboard operation
maps copied to clipboard

feat: remove deprecated RNMBXMapView's mapView & mapboxMap APIs

Open kainzhong opened this issue 4 months ago • 5 comments

Description

In our App, the deprecated APIs (RNMBXMapView.mapView & RNMBXMapView.mapboxMap) cause the app to crash because rnmapbox is trying to unwrap them while they are still nil.

This PR removes those two deprecated APIs and changes all their usage to the safe withMapView & withMapboxMap API calls. After this fix our app no longer crashes.

Checklist

  • [x] I've read CONTRIBUTING.md
  • [x] I updated the doc/other generated code with running yarn generate in the root folder
  • [ ] I have tested the new feature on /example app.
    • [ ] In V11 mode/ios
    • [ ] In New Architecture mode/ios
    • [] In V11 mode/android
    • [] In New Architecture mode/android
  • [x] I added/updated a sample - if a new feature was implemented (/example)

Screenshot OR Video

Component to reproduce the issue you're fixing

Kinda hard since the crash is triggered by an edge case in our app and we don't know how to create a minimal reproducing example yet but after I patched this package our app no longer crashes.

kainzhong avatar Sep 04 '25 22:09 kainzhong

@PRESIDENT810 thanks much for the PR

Unfortunately it's a bit complicated. Like in case of remove? withMapView could keep stuff alive and create a leak. So one thing we have to be carefully withMapView is leaks the other is concurrency, as the code will be called from other thread. And can cause deadlock and other issues.

Do you perhaps has stack traces? So we can address those cases, where you hit by the nil mapboxMap?

mfazekas avatar Sep 05 '25 04:09 mfazekas

@mfazekas Here's the stacktrace

          Crashed: com.apple.main-thread
0  <our app>                       0x2591ccc closure #5 in RNMBXMapView.setupEvents() + 1117 (RNMBXMapView.swift:1117)
1  <our app>                       0x258e554 specialized closure #1 in RNMBXMapView.onEvery<A>(event:handler:) + 305072
2  <our app>                       0x2597c38 partial apply for specialized closure #1 in RNMBXMapView.onNext<A>(event:handler:) + 343700 (<compiler-generated>:343700)
3  MapboxMaps                     0xb03cc closure #1 in MapboxObservable.onNext<A>(event:handler:) + 84
4  MapboxMaps                     0xb1950 partial apply for closure #1 in MapboxObservable.onNext<A>(event:handler:) + 20 (<compiler-generated>:20)
5  MapboxMaps                     0xb0524 @objc MapboxObservable.BlockObserver.notify(for:) + 166 (MapboxObservable.swift:166)
6  MapboxCoreMaps                 0x297f4 mapbox::bindgen::mapbox::maps::Observer::notify(mapbox::maps::Event const&) + 52
7  MapboxCoreMaps                 0x95644 mapbox::maps::ObserverWrapper::notify(mbgl::ObservableEvent const&) + 692
8  MapboxCoreMaps                 0x560d18 std::__1::__function::__func<mbgl::Observable::dispatchEvent(mbgl::ObservableEvent const&, mbgl::DispatchMode)::$_0, std::__1::allocator<mbgl::Observable::dispatchEvent(mbgl::ObservableEvent const&, mbgl::DispatchMode)::$_0>, void ()>::operator()() + 156
9  MapboxCommon                   0x4dc98 mapbox::common::platform::taskScope() + 1360
10 CoreFoundation                 0xf92c __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
11 CoreFoundation                 0xf744 __CFRunLoopDoSource0 + 172
12 CoreFoundation                 0xf604 __CFRunLoopDoSources0 + 332
13 CoreFoundation                 0xff20 __CFRunLoopRun + 840
14 CoreFoundation                 0x11adc CFRunLoopRunSpecific + 572
15 GraphicsServices               0x1454 GSEventRunModal + 168
16 UIKitCore                      0x135274 -[UIApplication _run] + 816
17 UIKitCore                      0x100a28 UIApplicationMain + 336
18 <our app>                       0xf9b4 main + 36 (main.m:36)

I can see the crash is caused by 5th closure in RNMBXMapView.setupEvents with "Swift runtime failure: Unexpectedly found nil while implicitly unwrapping an optional value" but I can't see what triggers it.

For leaks, I think I used [weak self] and tried my best to avoid circular reference here, and for concurrency, I think the callers to withMapView & withMapboxMap will not wait for anything. If RNMBXMapView._mapView is nil, then the closure is appended to waiters and the function returns immediately. It's basically promising to execute that closure as soon as _mapView is ready, and when it's ready, closures in waiter will execute serially, which I don't think would cause deadlocks.

kainzhong avatar Sep 05 '25 18:09 kainzhong

ping @mfazekas We've been using this patch in prod for a several weeks with good results - would love if this could merge to main so that we don't have to maintain our own patch. assuming others would benefit from this as well; happy to make more improvements in the future

kainzhong avatar Oct 01 '25 22:10 kainzhong

@PRESIDENT810 thanks again, and sorry for taking this long.

So generally there is 2 cases in the changes. 1.) Things like MapView.queryRenderedFeaturesInRect: withMapboxMap is good here, as we might have called queryRenderedFeaturesInRect before the map init has finished. Waiting for an underlying map view is great here. 2.) Components added to a specific map/style - I think they'd be better to store the map/style. I don't like withMapboxMap there as it might mean a different map/style we've already added the component.

mfazekas avatar Oct 11 '25 09:10 mfazekas

@PRESIDENT810 thanks much for the PR

Unfortunately it's a bit complicated. Like in case of remove? withMapView could keep stuff alive and create a leak. So one thing we have to be carefully withMapView is leaks the other is concurrency, as the code will be called from other thread. And can cause deadlock and other issues.

Do you perhaps has stack traces? So we can address those cases, where you hit by the nil mapboxMap?

@mfazekas
I encountered the same issue. Below is the library version information, "@rnmapbox/maps": "10.1.45", "react": "18.3.1", "react-native": "0.77.3", Below is the stack trace captured by Firebase

Crashlytics - Stack trace

Platform: apple

Issue: fe3bc65935115ec9828d90410e1d4584

Session: 95f85b7fd0464ae6bb83bd846f315998_DNE_0_v2

Date: Thu Nov 06 2025 15:15:20 GMT+0800 (中国标准时间)

Crashed: com.apple.main-thread 0 testAppIot 0xcb3e28 closure #2 in RNMBXMapView.setupEvents() + 1107 (RNMBXMapView.swift:1107) 1 testAppIot 0xcb112c specialized closure #1 in RNMBXMapView.onEvery<A>(event:handler:) + 940568 2 testAppIot 0xcba6dc partial apply for specialized closure #1 in RNMBXMapView.onNext<A>(event:handler:) + 978888 (:978888) 3 testAppIot 0x753ef0 closure #1 in MapboxObservable.onNext<A>(event:handler:) + 1045620 4 testAppIot 0x7554a8 partial apply for closure #1 in MapboxObservable.onNext<A>(event:handler:) + 1051180 (:1051180) 5 testAppIot 0x754048 @objc MapboxObservable.BlockObserver.notify(for:) + 166 (MapboxObservable.swift:166) 6 MapboxCoreMaps 0x297f4 mapbox::bindgen::mapbox::maps::Observer::notify(mapbox::maps::Event const&) + 52 7 MapboxCoreMaps 0x95644 mapbox::maps::ObserverWrapper::notify(mbgl::ObservableEvent const&) + 692 8 MapboxCoreMaps 0x56055c mbgl::Observable::dispatchEvent(mbgl::ObservableEvent const&, mbgl::DispatchMode) + 1472 9 MapboxCoreMaps 0x1b1c38 mbgl::MapObservableDispatcher::onStyleImageMissing(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator> const&) + 428 10 MapboxCoreMaps 0x1aceec non-virtual thunk to mbgl::Map::Impl::onStyleImageMissing(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator> const&, std::__1::function<void ()> const&) + 136 11 MapboxCoreMaps 0x251780 mbgl::ImageManager::checkMissingAndNotify(mbgl::ImageRequestor&, std::__1::pair<mbgl::ImageDependencies, unsigned long long> const&) + 1940 12 MapboxCoreMaps 0x53b4c4 mapbox::common::internal::Message<mbgl::GeometryTile, void (mbgl::GeometryTile::*)(std::__1::pair<mbgl::ImageDependencies, unsigned long long>), std::__1::tuple<std::__1::pair<mbgl::ImageDependencies, unsigned long long>>>::operator()() + 636 13 MapboxCommon 0x4dc98 mapbox::common::platform::taskScope() + 1360 14 CoreFoundation 0xfa8c CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + 28 15 CoreFoundation 0xf8a4 __CFRunLoopDoSource0 + 172 16 CoreFoundation 0xf764 __CFRunLoopDoSources0 + 332 17 CoreFoundation 0x10080 __CFRunLoopRun + 840 18 CoreFoundation 0x11c3c CFRunLoopRunSpecific + 572 19 GraphicsServices 0x1454 GSEventRunModal + 168 20 UIKitCore 0x135274 -[UIApplication _run] + 816 21 UIKitCore 0x100a28 UIApplicationMain + 336 22 testAppIot 0x39a5bc main + 14 (main.m:14) 23 ??? 0x1c711ff08 (缺少)

com.apple.uikit.eventfetch-thread 0 libsystem_kernel.dylib 0xce4 mach_msg2_trap + 8 1 libsystem_kernel.dylib 0x439c mach_msg2_internal + 76 2 libsystem_kernel.dylib 0x42b8 mach_msg_overwrite + 428 3 libsystem_kernel.dylib 0x4100 mach_msg + 24 4 CoreFoundation 0x11900 __CFRunLoopServiceMachPort + 160 5 CoreFoundation 0x101f0 __CFRunLoopRun + 1208 6 CoreFoundation 0x11c3c CFRunLoopRunSpecific + 572 7 Foundation 0xf79c -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212 8 Foundation 0x15020 -[NSRunLoop(NSRunLoop) runUntilDate:] + 64 9 UIKitCore 0x11f56c -[UIEventFetcher threadMain] + 424 10 Foundation 0x75804 NSThread__start + 732 11 libsystem_pthread.dylib 0x3344 _pthread_start + 136 12 libsystem_pthread.dylib 0xab8 thread_start + 8

com.google.firebase.crashlytics.MachExceptionServer 0 testAppIot 0x57d118 FIRCLSProcessRecordAllThreads + 392 (FIRCLSProcess.c:392) 1 testAppIot 0x57d4fc FIRCLSProcessRecordAllThreads + 423 (FIRCLSProcess.c:423) 2 testAppIot 0x57482c FIRCLSHandler + 34 (FIRCLSHandler.m:34) 3 testAppIot 0x577108 FIRCLSMachExceptionServer + 521 (FIRCLSMachException.c:521) 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8

com.apple.NSURLConnectionLoader 0 libsystem_kernel.dylib 0xce4 mach_msg2_trap + 8 1 libsystem_kernel.dylib 0x439c mach_msg2_internal + 76 2 libsystem_kernel.dylib 0x42b8 mach_msg_overwrite + 428 3 libsystem_kernel.dylib 0x4100 mach_msg + 24 4 CoreFoundation 0x11900 __CFRunLoopServiceMachPort + 160 5 CoreFoundation 0x101f0 __CFRunLoopRun + 1208 6 CoreFoundation 0x11c3c CFRunLoopRunSpecific + 572 7 CFNetwork 0xa030c +[__CFN_CoreSchedulingSetRunnable _run:] + 416 8 Foundation 0x75804 NSThread__start + 732 9 libsystem_pthread.dylib 0x3344 _pthread_start + 136 10 libsystem_pthread.dylib 0xab8 thread_start + 8

com.apple.CFSocket.private 0 libsystem_kernel.dylib 0x832c select$DARWIN_EXTSN + 8 1 libsystem_kernel.dylib 0x832c __select + 8 2 CoreFoundation 0x97a44 __CFSocketManager + 704 3 libsystem_pthread.dylib 0x3344 _pthread_start + 136 4 libsystem_pthread.dylib 0xab8 thread_start + 8

Thread 0 libsystem_kernel.dylib 0xa90 __workq_kernreturn + 8 1 libsystem_pthread.dylib 0xa58 _pthread_wqthread + 368 2 libsystem_pthread.dylib 0xaac start_wqthread + 8

com.facebook.react.JavaScript 0 libsystem_kernel.dylib 0xce4 mach_msg2_trap + 8 1 libsystem_kernel.dylib 0x439c mach_msg2_internal + 76 2 libsystem_kernel.dylib 0x42b8 mach_msg_overwrite + 428 3 libsystem_kernel.dylib 0x4100 mach_msg + 24 4 CoreFoundation 0x11900 __CFRunLoopServiceMachPort + 160 5 CoreFoundation 0x101f0 __CFRunLoopRun + 1208 6 CoreFoundation 0x11c3c CFRunLoopRunSpecific + 572 7 testAppIot 0x96bf38 +[RCTCxxBridge runRunLoop] + 347 (RCTCxxBridge.mm:347) 8 Foundation 0x75804 NSThread__start + 732 9 libsystem_pthread.dylib 0x3344 _pthread_start + 136 10 libsystem_pthread.dylib 0xab8 thread_start + 8

hades 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x212c4 std::__1::condition_variable::wait(std::__1::unique_lockstd::__1::mutex&) + 32 3 hermes 0xcc7fc hermes::vm::HadesGC::Executor::worker() + 116 4 hermes 0xcc764 void* std::__1::__thread_proxy[abi:v160006]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_deletestd::__1::__thread_struct>, hermes::vm::HadesGC::Executor::Executor()::'lambda'()>>(void*) + 44 5 libsystem_pthread.dylib 0x3344 _pthread_start + 136 6 libsystem_pthread.dylib 0xab8 thread_start + 8

com.mapbox.common.Worker 1 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x2135c std::__1::condition_variable::__do_timed_wait(std::__1::unique_lockstd::__1::mutex&, std::__1::chrono::time_point<std::__1::chrono::system_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l>>>) + 104 3 MapboxCommon 0x716c8 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1360 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8

com.mapbox.common.Worker 2 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x2135c std::__1::condition_variable::__do_timed_wait(std::__1::unique_lockstd::__1::mutex&, std::__1::chrono::time_point<std::__1::chrono::system_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l>>>) + 104 3 MapboxCommon 0x716c8 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1360 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8

com.mapbox.common.Worker 3 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x2135c std::__1::condition_variable::__do_timed_wait(std::__1::unique_lockstd::__1::mutex&, std::__1::chrono::time_point<std::__1::chrono::system_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l>>>) + 104 3 MapboxCommon 0x716c8 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1360 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8

com.mapbox.common.Worker 4 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x2135c std::__1::condition_variable::__do_timed_wait(std::__1::unique_lockstd::__1::mutex&, std::__1::chrono::time_point<std::__1::chrono::system_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l>>>) + 104 3 MapboxCommon 0x716c8 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1360 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8

com.mapbox.common.location.sharedRunloop 0 libsystem_kernel.dylib 0xce4 mach_msg2_trap + 8 1 libsystem_kernel.dylib 0x439c mach_msg2_internal + 76 2 libsystem_kernel.dylib 0x42b8 mach_msg_overwrite + 428 3 libsystem_kernel.dylib 0x4100 mach_msg + 24 4 CoreFoundation 0x11900 __CFRunLoopServiceMachPort + 160 5 CoreFoundation 0x101f0 __CFRunLoopRun + 1208 6 CoreFoundation 0x11c3c CFRunLoopRunSpecific + 572 7 CoreFoundation 0x8c674 CFRunLoopRun + 64 8 MapboxCommon 0xde3c0 mapbox::common::location::LocationServiceFactory::locationService() + 66872 9 Foundation 0x75804 NSThread__start + 732 10 libsystem_pthread.dylib 0x3344 _pthread_start + 136 11 libsystem_pthread.dylib 0xab8 thread_start + 8

com.mapbox.common.AssetFileSource 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x212c4 std::__1::condition_variable::wait(std::__1::unique_lockstd::__1::mutex&) + 32 3 MapboxCommon 0x71698 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1312 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8

com.mapbox.common.TileStoreFileSource 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x212c4 std::__1::condition_variable::wait(std::__1::unique_lockstd::__1::mutex&) + 32 3 MapboxCommon 0x71698 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1312 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8

com.mapbox.common.LocalFileSource 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x212c4 std::__1::condition_variable::wait(std::__1::unique_lockstd::__1::mutex&) + 32 3 MapboxCommon 0x71698 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1312 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8

com.mapbox.common.OnlineFileSource 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x2135c std::__1::condition_variable::__do_timed_wait(std::__1::unique_lockstd::__1::mutex&, std::__1::chrono::time_point<std::__1::chrono::system_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l>>>) + 104 3 MapboxCommon 0x716c8 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1360 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8

com.mapbox.common.ResourceLoaderThread 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x212c4 std::__1::condition_variable::wait(std::__1::unique_lockstd::__1::mutex&) + 32 3 MapboxCommon 0x71698 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1312 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8

Thread 0 libsystem_pthread.dylib 0xaa4 start_wqthread + 442

Thread 0 libsystem_pthread.dylib 0xaa4 start_wqthread + 442

Thread 0 libsystem_pthread.dylib 0xaa4 start_wqthread + 442

Thread 0 libsystem_kernel.dylib 0xa90 __workq_kernreturn + 8 1 libsystem_pthread.dylib 0xa58 _pthread_wqthread + 368 2 libsystem_pthread.dylib 0xaac start_wqthread + 8

Thread 0 libsystem_kernel.dylib 0xa90 __workq_kernreturn + 8 1 libsystem_pthread.dylib 0xa58 _pthread_wqthread + 368 2 libsystem_pthread.dylib 0xaac start_wqthread + 8

Thread 0 libsystem_kernel.dylib 0xce4 mach_msg2_trap + 8 1 libsystem_kernel.dylib 0x439c mach_msg2_internal + 76 2 libsystem_kernel.dylib 0x42b8 mach_msg_overwrite + 428 3 libsystem_kernel.dylib 0x4100 mach_msg + 24 4 CoreFoundation 0x11900 __CFRunLoopServiceMachPort + 160 5 CoreFoundation 0x101f0 __CFRunLoopRun + 1208 6 CoreFoundation 0x11c3c CFRunLoopRunSpecific + 572 7 Foundation 0xf79c -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212 8 testAppIot 0x4b456c -[AWSIoTStreamThread main] + 98 (AWSIoTStreamThread.m:98) 9 Foundation 0x75804 NSThread__start + 732 10 libsystem_pthread.dylib 0x3344 _pthread_start + 136 11 libsystem_pthread.dylib 0xab8 thread_start + 8

leeeGreat avatar Nov 08 '25 11:11 leeeGreat