This was why I suggested flushing during login, instead of or in addition to logout.
That's the thing. Everything associated with the XMPPLink instance attached to the player already is flushed in the connection callback, mostly to clear things out if you /xmppconnect after losing the XMPP connection without a clean disconnect.
However, that won't help if the problem is (1) or (2), because that means the entities you're seeing are associated with a different XMPPLink. Proxies are shared between link instances to avoid unnecessary duplication if you have multiple clients connected simultaneously. You can flush it all you want, but you only have access to your own link, not to the other player's that is stuck in limbo.
Simply destroying all entities on the map at login regardless if they are still referenced just hides the problem. Not only does it break multi-instancing entirely*, but you'd still be left with whatever problem was causing them to not be destroyed. Instead of knowing about it, it would be invisible and possibly causing worse problems, such as a crash if whatever is holding the reference tries to access them after they are removed.
It could also be something holding onto a roomlink from another session somehow. That would keep the room alive, which in turn would keep all of the occupants alive, and if the room was the meta channel, would keep the proxies alive. To give you an idea of the complexity involved, here's a comment that might shed some light:
// Why all this rigmarole of XMPPLink -> RoomLink -> Room? Theoretically one player
// entity could be in a room hosting the map they're running around on, while another
// could add that same room as a global chat channel. The room JID is the same for
// both, so the XMPPIdentity (which is global) refers to the same room. That's good
// in that they can share the occupant list, but bad in that the handler callback needs
// to do different things for incoming messages in zones versus global channels.
// Even multiple players in the same channel is a problem, as the messages need to
// go different places depending on which link they arrived over, and the room may
// be in different states (currently connecting versus active member) on each session.
// We don't officially support multiple players on one ParagonChat instance, but
// since the mapserver protocol has no concept of a global 'one true player', keeping
// state on a per-XMPPLink basis is the only sensible implementation.
// This gets even more complicated if the same RoomLink is needed in multiple
// contexts for the same entity (i.e. the same XMPP room JID added as two separate
// channels). We can't join the same room more than once on a given XMPP session,
// so add yet another layer to hold the callback functions to handle messages.
// Final layout looks something like this:
//
// XMPPRoomHandle - Context, incoming message callback, and user data per handle.
// \-> XMPPRoomLink - Shared state for the room across the entire XMPPLink,
// | evaporates when last handle to it is released.
// \-> XMPPRoom - Global room information, is cleaned up when no more XMPPRoomLinks
// reference it. Holds occupant list.
This would also help a bug I've encountered several times where someone else who has hit this bug has sent chat to my client until they restart the PC client.
It actually wouldn't help with that at all. The problem there is that your friend somehow didn't see your unavailable <presence/> and still thinks that you're in the zone's meta channel, so they are sending their local chat to you. There's nothing you can do on your end about that**, and correcting the inconsistent state requires your friend's cooperation, usually by disconnecting and reconnecting to XMPP.
* While multi-instancing is not something that's supported or even advertised that it's possible, it's not something I want to sacrifice as it helps keep the backend clean and free of special-case hacks that assume only one player at a time.
** If you're still logged in to the same resource as the one they saw you on, going to the zone they're in and then leaving may cause them to realize that you've left.