Closed calebmackdavenport closed 2 months ago
Apologies if this is less than ideal of a submission. I do not like opening issues for problems that I cannot consistently recreate.
Happy to be incorrect, but it seems like an iOS ecosystem problem that I'm not able to discern if there's an available resolution for. I noticed 4.15.0 is available, but wanted to post this issue as I was not certain if the concerns addressed in the changelog matched up with what I'm seeing reports of.
4.15.0
didn't make any changes to iOS. There haven't been changes to iOS in a relatively long time.
Was this issue closed on-purpose?
Yep. I was not aware of a change behind a feature flag where we were calling getCurrentPosition
concurrently 🤦🏼♂️
Thank you for checking. Apologies for the false alarm.
where we were calling getCurrentPosition concurrently
Can you show me a quick example of what the javascript for that looks like? The plugin should be able to handle concurrent calls to .getCurrentPosition
.
Mmm, we have the queue as noted above to avoid this circumstance.
This would've been an example of the code in question that caused the problem:
const _getLocation = async () => {
const {
coords: { latitude, longitude, accuracy, heading, speed },
timestamp
} = await BackgroundGeolocation.getCurrentPosition();
return {
latitude,
longitude,
accuracy,
observed: timestamp,
heading,
speed
};
};
To remedy, we needed to ensure that we were calling our internal getCurrentPosition which uses a queue:
export const getCurrentPosition = async (extras = {}) => {
try {
await PermissionsStore.useLocationPermission();
await initialize();
let resolve;
const pendingPromise = new Promise(r => (resolve = r));
_pendingLocationPings.push({ extras, pendingPromiseResolve: resolve });
_emptyLocationPingQueue();
return pendingPromise;
} catch {}
};
rather than BackgroundGeolocation.getCurrentPosition()
directly.
Having multiple instances of BackgroundGeolocation.getCurrentPosition()
in various services firing at app launch (or post-authentication), we run into errors like the one above:
1 libsystem_platform.dylib +0x32d8 __os_unfair_lock_lock_slow
2 libobjc.A.dylib +0x84b0 _objc_sync_enter
3 app +0xfb95c0 -[TSLocationManager queue:type:]
4 app +0xfb5598 -[TSLocationManager onUpdateCurrentPosition:location:type:]
So we use the queue (_processQueue
function above), which just works through an array to ensure that we resolve BackgroundGeolocation.getCurrentPosition
before calling it again.
I am happy to share additional information or configuration we have, but I am not sure what would be helpful.
You shouldn't need to manage queues in Javascript. The plug-in already does queuing of requests in Obj-c.
I'd really like a repeatable sample of code that reproduces it so I can see what's up.
I'm also having many of these, but still no success in finding reproducible steps.
App Hang TSLocationManager The app was terminated while unresponsive
Your Environment
react-native -v
): 0.71.14Plugin config
export const getCurrentPosition = async (extras = {}) => { try { await PermissionsStore.useLocationPermission(); await initialize(); let resolve; const pendingPromise = new Promise(r => (resolve = r)); _pendingLocationPings.push({ extras, pendingPromiseResolve: resolve }); _emptyLocationPingQueue(); return pendingPromise; } catch {} };
let _queueIsRunning = false; const _emptyLocationPingQueue = async () => { if (_queueIsRunning) return; _queueIsRunning = true;
try { await _processQueue(); } finally { _queueIsRunning = false; } };
const _processQueue = async () => { const pendingPing = _pendingLocationPings.shift(); if (!pendingPing) return; try { const location = await BackgroundGeolocation.getCurrentPosition({ timeout: 30, maximumAge: 5000, desiredAccuracy: 10, persist: true, extras: pendingPing.extras }); pendingPing.pendingPromiseResolve(location); } catch { pendingPing.pendingPromiseResolve(); } return _processQueue(); };