Unfortunately I think this is just one of a whole class of race
conditions caused by errored channels being unloaded immediately without
waiting for the refcounter to reach 0.
However, this one is the only one that appears commonly in the logs so
adding this check should buy time to rethink the overall problem.
Fixes#681. Technically, resending the entire userlist is not
necessary; it would be sufficient to resent setUserMeta, but there's not
currently a bulk frame for that so sending the userlist is probably more
efficient.
User.prototype.refreshAccount was responsible for multiple race
condition bugs as well as inefficient duplication of DB queries in an
attempt to correct such race conditions.
It has now been replaced by a more reasonable model:
* Global user account information and aliases are fetched in parallel
on socket connection
* Channel rank is fetched when the user tries to join a channel
The previous commits do not handle all of the edge cases of #583
appropriately. This is a short term solution that will work, but is not
as efficient as it could be. The whole refreshAccount function needs to
be reconsidered and replaced with a more sane way of handling atomic
updates to the user's account state.
Instead of emitting frames to each individual socket, group them into
socket.io rooms of people who can see hidden poll results and people who
can't, then just do 2 broadcasts.
CyTube has been crashing recently due to things attempting to release
the reference after the channel was already closed (apparently the
uncaughtException handler isn't called for this?). This newer
implementation keeps track of what is ref'ing and unref'ing it, so it
can log an error if it detects a discrepancy.
Also changed the server to not delete the refCounter field from the
channel when it's unloaded, so that should reduce the number of errors
stemming from it being null/undefined.