I think this is the least intrusive fix for the chat crashes: lock the agent

list when we're updating from the network, simulating, or rendering.  I think
there are likely to be other synchronization issues, but this is a start.
This commit is contained in:
Andrzej Kapolka 2013-04-29 13:17:39 -07:00
parent 84a8af4808
commit 0fe4d57ad7
3 changed files with 15 additions and 1 deletions

View file

@ -867,12 +867,14 @@ void display(void)
// Render avatars of other agents // Render avatars of other agents
AgentList* agentList = AgentList::getInstance(); AgentList* agentList = AgentList::getInstance();
agentList->lock();
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) { if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) {
Avatar *avatar = (Avatar *)agent->getLinkedData(); Avatar *avatar = (Avatar *)agent->getLinkedData();
avatar->render(0); avatar->render(0);
} }
} }
agentList->unlock();
// Render the world box // Render the world box
if (!::lookingInMirror && ::statsOn) { render_world_box(); } if (!::lookingInMirror && ::statsOn) { render_world_box(); }
@ -1486,12 +1488,14 @@ void idle(void) {
//loop through all the other avatars and simulate them... //loop through all the other avatars and simulate them...
AgentList* agentList = AgentList::getInstance(); AgentList* agentList = AgentList::getInstance();
agentList->lock();
for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
if (agent->getLinkedData() != NULL) { if (agent->getLinkedData() != NULL) {
Avatar *avatar = (Avatar *)agent->getLinkedData(); Avatar *avatar = (Avatar *)agent->getLinkedData();
avatar->simulate(deltaTime); avatar->simulate(deltaTime);
} }
} }
agentList->unlock();
myAvatar.simulate(deltaTime); myAvatar.simulate(deltaTime);

View file

@ -66,7 +66,7 @@ AgentList::AgentList(char newOwnerType, unsigned int newSocketListenPort) :
socketListenPort(newSocketListenPort), socketListenPort(newSocketListenPort),
lastAgentId(0) lastAgentId(0)
{ {
pthread_mutex_init(&mutex, 0);
} }
AgentList::~AgentList() { AgentList::~AgentList() {
@ -74,6 +74,8 @@ AgentList::~AgentList() {
stopSilentAgentRemovalThread(); stopSilentAgentRemovalThread();
stopDomainServerCheckInThread(); stopDomainServerCheckInThread();
stopPingUnknownAgentsThread(); stopPingUnknownAgentsThread();
pthread_mutex_destroy(&mutex);
} }
UDPSocket& AgentList::getAgentSocket() { UDPSocket& AgentList::getAgentSocket() {
@ -106,6 +108,8 @@ void AgentList::processAgentData(sockaddr *senderAddress, unsigned char *packetD
} }
void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes) { void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes) {
lock();
// find the avatar mixer in our agent list and update the lastRecvTime from it // find the avatar mixer in our agent list and update the lastRecvTime from it
Agent* bulkSendAgent = agentWithAddress(senderAddress); Agent* bulkSendAgent = agentWithAddress(senderAddress);
@ -141,6 +145,8 @@ void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *pac
packetHolder, packetHolder,
numTotalBytes - (currentPosition - startPosition)); numTotalBytes - (currentPosition - startPosition));
} }
unlock();
} }
int AgentList::updateAgentWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) { int AgentList::updateAgentWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) {

View file

@ -53,6 +53,9 @@ public:
uint16_t getLastAgentId(); uint16_t getLastAgentId();
void increaseAgentId(); void increaseAgentId();
void lock() { pthread_mutex_lock(&mutex); }
void unlock() { pthread_mutex_unlock(&mutex); }
int updateList(unsigned char *packetData, size_t dataBytes); int updateList(unsigned char *packetData, size_t dataBytes);
Agent* agentWithAddress(sockaddr *senderAddress); Agent* agentWithAddress(sockaddr *senderAddress);
@ -99,6 +102,7 @@ private:
pthread_t removeSilentAgentsThread; pthread_t removeSilentAgentsThread;
pthread_t checkInWithDomainServerThread; pthread_t checkInWithDomainServerThread;
pthread_t pingUnknownAgentsThread; pthread_t pingUnknownAgentsThread;
pthread_mutex_t mutex;
void handlePingReply(sockaddr *agentAddress); void handlePingReply(sockaddr *agentAddress);
}; };