Jump to content

OpenSimulator Internals/Walkthroughs/Avatar Logs Out

From Open Simulator Technical Help

OpenSimulator Internals/Walkthroughs/Avatar Logs Out

[edit]

Overview

[edit]

Traces what happens in code, connectors, and database when an avatar logs out normally. Covers both viewer-initiated logout and region-initiated close.

This does not cover region crossing or teleport departure -- see OpenSimulator Internals/Walkthroughs/Avatar Transfer Between Regions.


1. Logout Initiated

[edit]

Viewer-initiated

[edit]
OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
  1. Avatar clicks Logout in viewer.
  2. Viewer sends LogoutRequest UDP packet.
  3. LLClientView.HandleLogout() fires. Sets IsLoggingOut = true on the client.
  4. Calls Scene.CloseAgent(agentID, force=false).

Region-initiated (admin kick or simulator shutdown)

[edit]
  1. Console command or admin API calls Scene.CloseAgent(agentID, force=true).
  2. Or: LLClientView.OnConnectionClosed fires when viewer connection drops; EntityTransferModule.OnConnectionClosed() sets transfer state to Aborting if in transit.

2. Scene.CloseAgent()

[edit]
OpenSim/Region/Framework/Scenes/Scene.cs -- CloseAgent()

Under m_removeClientLock:

  1. Gets ScenePresence. If null or IsDeleted: removes from clientManager, authenticateHandler, capsModule directly and returns.
  2. Checks LifecycleState -- must be Running or PreRemove to proceed.
  3. Checks DoNotCloseAfterTeleport -- if true (another region renewed the child connection), resets flag and returns false without closing.
  4. Sets sp.LifecycleState = Removing.

Then outside the lock:

  1. Calls sp.ControllingClient.Close(force, force) -- this triggers RemoveClient() via the client stack.
  2. For NPCs: calls UserManagementModule.RemoveUser().

3. RemoveClient()

[edit]
OpenSim/Region/Framework/Scenes/Scene.cs -- RemoveClient()

Under m_removeClientPrivLock:

  1. Gets AgentCircuitData -- if null, aborts.
  2. Gets ScenePresence -- if null, removes circuit and returns.
  3. If child agent and closeChildAgents: sends SendShutdownConnectionNotice() to viewer.
  4. If avatar is sitting: calls avatar.StandUp().
  5. Calls m_sceneGraph.removeUserCount(!isChildAgent).
  6. If root agent and closeChildAgents:
    • Gets KnownRegionHandles (all known neighbour regions).
    • Calls m_sceneGridService.SendCloseChildAgentConnections() -- async HTTP DELETE to each neighbour simulator's agent endpoint.
  7. Fires EventManager.TriggerClientClosed().
  8. Fires EventManager.TriggerOnRemovePresence().
  9. If root agent:
    • Calls AttachmentsModule.DeRezAttachments() -- saves all attachments to inventory (see step 4).
    • Calls ForEachClient() sending SendKillObject for this avatar's LocalId to all connected clients.
  10. Calls AgentTransactionsModule.RemoveAgentAssetTransactions() if present.

Finally (in finally block, always runs):

  1. m_authenticateHandler.RemoveCircuit(acd).
  2. m_sceneGraph.RemoveScenePresence(agentID).
  3. m_clientManager.Remove(agentID).
  4. m_capsModule.RemoveCaps(agentID, circuitcode).
  5. avatar.Dispose().

Note: PresenceService.LogoutAgent() and GridUserService.LoggedOut() are NOT called from RemoveClient(). These are called from LLClientView.Close() or from the login service cleanup path. See step 5.


4. Attachments Saved

[edit]
OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs -- DeRezAttachments()

For each attachment SOG:

  1. Calls PrepareScriptInstanceForSave() -- fires detach script event, waits 30ms, snapshots script state XML. Must run outside AttachmentsSyncLock.
  2. Calls UpdateDetachedObject():
    • Calls m_scene.DeleteSceneObject() -- removes from scene.
    • Clears attachment fields (AttachedAvatar, ParentLocalId, IsAttachment).
    • For local grid users only (not HG visitors): calls UpdateKnownItem() -- serialises SOG to XML, creates new asset, updates inventory item assetID and permissions.
    • Calls so.RemoveScriptInstances() + so.Dispose().
  3. Calls sp.ClearAttachments().

HG visitors: UpdateKnownItem() skipped. Their attachments are not saved to the foreign grid. When they log back in on their home grid, attachments reload from home grid state.

DB writes
  • assets -- INSERT: updated serialised object XML per attachment (local users only)
  • inventoryitems -- UPDATE: new assetID per attachment (local users only)

5. Presence and GridUser Updated

[edit]
OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs -- Close()
OpenSim/Services/Connectors/Presence/PresenceServicesConnector.cs
OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs

On client close (called from CloseAgent step 2):

  1. PresenceService.LogoutAgent(sessionID) called -- HTTP POST to ROBUST PresenceService.
    • ROBUST sets presence Online=0, clears RegionID for this session.
  2. GridUserService.LoggedOut(agentID, sessionID, regionID, position, lookAt) called -- HTTP POST to ROBUST GridUserService.
    • ROBUST updates griduser: LastRegionID, LastPosition, LastLookAt, Logout timestamp.
DB writes
  • presence -- UPDATE: Online=0, RegionID cleared
  • griduser -- UPDATE: LastPosition, LastLookAt, LastRegionID, Logout timestamp

6. Child Agents Closed

[edit]

Called asynchronously from RemoveClient() step 3 via m_sceneGridService.SendCloseChildAgentConnections().

For each neighbour handle in KnownRegionHandles:

  1. HTTP DELETE to neighbour simulator's agent endpoint (SimulationService).
  2. Neighbour simulator receives request, validates auth token (SessionID).
  3. Calls Scene.CloseAgent() on the child ScenePresence.
  4. Child path: no attachment save, no presence update, just removes from scene graph.

7. Appearance Save (if queued)

[edit]

If an appearance save was queued via AvatarFactoryModule and the 5-second delay has not yet elapsed:

  • AvatarFactoryModule timer fires SaveAppearance().
  • Calls AvatarService.SetAppearance() -- writes final appearance to ROBUST.

Whether this completes before or after the logout depends on timing. A logout immediately after an outfit change may race with or skip the final save.

DB writes (conditional)
  • avatarappearance -- UPDATE: final wearable list, textures, visual params

Shutdown vs Normal Logout

[edit]

Scene.Close() (simulator shutdown):

  1. Fires EventManager.TriggerSceneShuttingDown().
  2. Calls GridService.DeregisterRegion() -- removes region from regions table. Sets RegionOnline=0.
  3. Sends Kick message to all root avatars via ControllingClient.Kick().
  4. Sends SendShutdownConnectionNotice() to all.
  5. Sleeps 500ms for messages to deliver.
  6. Calls CloseAgent() for every ScenePresence.
  7. Calls Backup(true) -- forces persistence of all changed scene objects.
  8. Closes SceneGraph and disposes PhysicsScene.
DB writes (on shutdown)
  • regions -- UPDATE: RegionOnline=0 (via GridService.DeregisterRegion())
  • prims/primshapes/primitems -- UPDATE: all changed objects persisted via Backup(true)
  • presence/griduser -- UPDATE: as per normal logout for each agent

Summary: DB Tables Touched

[edit]
Table Operation Step
assets INSERT Attachment object assets saved (step 4, local users)
inventoryitems UPDATE Attachment inventory items updated (step 4, local users)
presence UPDATE Online=0, session cleared (step 5)
griduser UPDATE LastPosition, Logout timestamp (step 5)
avatarappearance UPDATE Final appearance if save queued (step 7, conditional)
regions UPDATE RegionOnline=0 on shutdown only
prims/primshapes UPDATE Changed objects on shutdown only

Simultaneous Logout During Teleport

[edit]

If the client sends LogoutRequest while a teleport is in progress:

  1. EntityTransferModule.OnConnectionClosed() fires.
  2. If agent is in transit: sets transfer state to Aborting.
  3. The in-progress teleport path checks Aborting state at each stage and aborts.
  4. Source region calls CleanupFailedInterRegionTeleport() -- calls SimulationService.CloseAgent() on destination to remove the half-created agent there.

See Also

[edit]