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
Fix #609 #628
Fix #609 #628
Conversation
The world lock seems like its doing too much. It's guarding a couple cases where the entity modifies GlowWorld, but at the same time its guarding the problems with knownEntities, which doesn't seem to touch the world, nor the world touch knownEntities? Since the initial bug was around knownEntities, it seems a ReadWriteLock would be in order here, with canSeeEntity() acquiring a read lock while hidePlayer(), pulse(), and respawn() acquire the write lock. Or am I missing something here? |
Switched to a readWriteLock. respawn() will also acquire the write lock, since it too can update knownEntities. In other words, worldLock guards both world and knownEntities. |
I still don't understand why you are (re-)using this lock for the .unregister() and .register() calls. I didn't see it accessing the knownEntities collection at any point. |
To ensure that when we register with the destination world, a spawn or another teleport hasn't moved us outside of that world (which may have something to do with bug #630 ). |
I think then that there should be a second lock for that case. Over reliance on a single lock for two different use cases can cause confusion as well as performance problems. |
But using two separate locks will mean world and knownEntities can be out of sync, with IDs being misinterpreted because they're from a different world. @Momothereal, what do you think? BTW, I'm now pretty sure #609 and #630 are related, since when I tested this PR, I only got Nether chunks in the Overworld, whereas I'd previously gotten End chunks as well. |
So, I did some deep diving into this code, and this doesn't appear to be operating quite how you expect it to. If you want to keep both collections in sync, you'll need to move the lock up to where both items are being manipulated, such as the GlowPlayer.respawn() method. What'll happen right now, taking the aforementioned method as an example, is:
As you can see, the lock was acquired and twice (two separate instances at that), and between the first instance being released 3 and the second instance being acquired in 5, the GlowPlayer could be manipulated, making the two go out of sync. The fix to this is to make sure you never release the lock while working on either of these operations. |
Thanks! I've fixed that case. As well, respawn() will also hold the lock while querying the player's world for a default spawn location (although I think that affects only modded servers, since players who die in the Nether or End, or who fall into a Nether/End portal while dead, would respawn in the Overworld in vanilla). |
This fix uses a lock that is acquired by teleport(), pulse() and spawnAt(). We can add it in more places if needed.