I've been chasing this bug for weeks. Getting crash due to EXC_BAD_ACCESS (code=EXC_I386_GPFLT) frequently (~25% of the time) when backgrounding and re-foregrounding iOS app. We are using iOS Runtime 100.2.1. Crash is occurring across device types and iOS versions. Any help in identifying a workaround would be appreciated.
Our implementation:
1) all tables and layers instantiated from local runtime replica geodatabase (regsGDB.geodatabase):
fileprivate func initGDB() -> Void {
self.deinitGDB()
regsGDB = AGSGeodatabase(fileURL: FileUtil.urlFor(GlobalConstants.fileNames.REGS_WORKING_GDB)!)
regsGDB.load(completion: {[weak self] (error: Error?) in
if (error != nil) {
self?.regsGDBLoaded = false
self?.disableFeatureInteraction()
os_log("Error loading geodatabase", [error?.localizedDescription])
} else {
self?.loadLayers()
}})
}
2) strong references to tables and layers, with nil checks on regsGDB before calling load (for tables and layers):
fileprivate func loadLayers() -> Void {
if regsGDB != nil && regsGDB.loadStatus == .loaded {
self.countiesTable = (regsGDB.geodatabaseFeatureTable(byServiceLayerID: GlobalConstants.IDs.COUNTIES_LAYER_INDEX)!) as AGSFeatureTable
self.countiesLayer = AGSFeatureLayer(featureTable: (self.countiesTable)!)
self.countiesLayer.renderer = EsriUtil.municipalityPolyRenderer
self.countiesLayer.labelsEnabled = true
self.countiesLayer.selectionColor = UIColor.cyan
self.countiesLayer.selectionWidth = 5
self.countiesLayer.minScale = 6000000
self.map.operationalLayers.add(self.countiesLayer)
self.citiesTable = (regsGDB.geodatabaseFeatureTable(byServiceLayerID: GlobalConstants.IDs.CITIES_LAYER_INDEX)!) as AGSFeatureTable
self.citiesLayer = AGSFeatureLayer(featureTable: (self.citiesTable)!)
self.citiesLayer.renderer = EsriUtil.municipalityPolyRenderer
self.citiesLayer.labelsEnabled = true
self.citiesLayer.selectionColor = UIColor.cyan
self.citiesLayer.selectionWidth = 5
self.citiesLayer.minScale = 6000000
self.map.operationalLayers.add(self.citiesLayer)
.
.
.
3) deinit by manually removing all operationalLayers and tables, nilling out all layers and tables prior to reinitializing and loading gdb, tables and layers:
fileprivate func deinitGDB() -> Void {
// remove and nil out the layers
self.map.operationalLayers.removeAllObjects()
self.countiesLayer = nil
self.citiesLayer = nil
.
.
.
// remove and nil out the tables
self.map.tables.removeAllObjects()
self.countiesTable = nil
self.citiesTable = nil
.
.
.
if regsGDB != nil {
switch regsGDB.loadStatus {
case .loading:
regsGDB.cancelLoad()
break
default:
break
}
regsGDB.close()
}
regsGDBLoaded = false
}
I have not been able to reproduce by stepping through/over. Thoughts?
Attached is a debug log of ObjC and C++ Exceptions encountered on foregrounding repeatedly in the same session. Note, crash only occurs when breakpoints are turned off (see crash again in last backtrace in this file).
Here's a back-trace of the crash (full stack is attached):
* thread #67, queue = 'com.apple.root.default-qos', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
* frame #0: 0x000000010f2574b4 ArcGIS`columnMem + 88
frame #1: 0x000000010f257535 ArcGIS`ags_sqlite3_column_bytes + 15
frame #2: 0x000000010e87a38d ArcGIS`Esri_runtimecore::Geodatabase::Sqlite_command::get_as_text(int) + 77
frame #3: 0x000000010e81287e ArcGIS`Esri_runtimecore::Geodatabase::Bound_row_value::operator std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >() const + 28
frame #4: 0x000000010e848b6d ArcGIS`Esri_runtimecore::Geodatabase::populate_field_definitions(std::__1::shared_ptr<Esri_runtimecore::Geodatabase::Database>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) + 503
frame #5: 0x000000010e814079 ArcGIS`Esri_runtimecore::Geodatabase::Catalog_dataset::get_item_definition(Esri_runtimecore::Geodatabase::Catalog_item_reference const&) + 2825
frame #6: 0x000000010e890fce ArcGIS`Esri_runtimecore::Geodatabase::Details::Table_schema::describe(std::__1::shared_ptr<Esri_runtimecore::Geodatabase::Database>&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) + 232
frame #7: 0x000000010e891aab ArcGIS`Esri_runtimecore::Geodatabase::Details::Table_schema::open(std::__1::shared_ptr<Esri_runtimecore::Geodatabase::Database>&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) + 191
frame #8: 0x000000010e8ad763 ArcGIS`std::__1::shared_ptr<Esri_runtimecore::Geodatabase::Table> Esri_runtimecore::Geodatabase::Database::open<Esri_runtimecore::Geodatabase::Table>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) + 51
frame #9: 0x000000010da7a276 ArcGIS`Esri_runtimecore::Mapping::Geodatabase_feature_table::load_sync(pplx::cancellation_token) + 206
frame #10: 0x000000010da7cc3a ArcGIS`std::__1::__function::__func<Esri_runtimecore::Mapping::Geodatabase_feature_table::load_or_retry_(Esri_runtimecore::Mapping::Loadable::Load_or_retry_mode)::$_2, std::__1::allocator<Esri_runtimecore::Mapping::Geodatabase_feature_table::load_or_retry_(Esri_runtimecore::Mapping::Loadable::Load_or_retry_mode)::$_2>, void ()>::operator()() + 150
frame #11: 0x000000010db748b2 ArcGIS`std::__1::__function::__func<Esri_runtimecore::Mapping::Task<void>::Task(std::__1::function<void ()>, pplx::cancellation_token_source)::'lambda'(), std::__1::allocator<Esri_runtimecore::Mapping::Task<void>::Task(std::__1::function<void ()>, pplx::cancellation_token_source)::'lambda'()>, boost::any ()>::operator()() + 18
frame #12: 0x000000010deeb4fb ArcGIS`std::__1::function<boost::any ()>::operator()() const + 27
frame #13: 0x000000010deeb75e ArcGIS`std::__1::__function::__func<Esri_runtimecore::Mapping::Task_implementation::Task_implementation(std::__1::function<boost::any ()>, Esri_runtimecore::Mapping::Task_options)::$_0, std::__1::allocator<Esri_runtimecore::Mapping::Task_implementation::Task_implementation(std::__1::function<boost::any ()>, Esri_runtimecore::Mapping::Task_options)::$_0>, boost::any ()>::operator()() + 50
frame #14: 0x000000010deeb4fb ArcGIS`std::__1::function<boost::any ()>::operator()() const + 27
frame #15: 0x000000010deeb28f ArcGIS`pplx::details::_PPLTaskHandle<boost::any, pplx::task<boost::any>::_InitialTaskHandle<boost::any, Esri_runtimecore::Mapping::Task_implementation::Task_implementation(std::__1::function<boost::any ()>, Esri_runtimecore::Mapping::Task_options)::$_0, pplx::details::_TypeSelectorNoAsync>, pplx::details::_TaskProcHandle>::invoke() const + 267
frame #16: 0x000000010f55d5c4 ArcGIS`pplx::details::_TaskProcHandle::_RunChoreBridge(void*) + 16
frame #17: 0x000000010ee1b428 ArcGIS`Esri_runtimecore::Common::Core_scheduler::invoke_(Esri_runtimecore::Common::Core_scheduler::Queued_proc*) + 24
frame #18: 0x000000010ee1b3d0 ArcGIS`Esri_runtimecore::Common::Core_scheduler::Queued_proc::invoke() + 48
frame #19: 0x000000010ee1ad1f ArcGIS`Esri_runtimecore::Common::Core_scheduler::bridge_proc_(void*) + 23
frame #20: 0x0000000119e8a848 libdispatch.dylib`_dispatch_client_callout + 8
frame #21: 0x0000000119e8f675 libdispatch.dylib`_dispatch_queue_override_invoke + 1451
frame #22: 0x0000000119e963c8 libdispatch.dylib`_dispatch_root_queue_drain + 664
frame #23: 0x0000000119e960d2 libdispatch.dylib`_dispatch_worker_thread3 + 132
frame #24: 0x000000011c615169 libsystem_pthread.dylib`_pthread_wqthread + 1387
frame #25: 0x000000011c614be9 libsystem_pthread.dylib`start_wqthread + 13
(lldb)