We tried to lay out a level making every cell only able to have one portal out of it per wall, but that was a pain, so we had to fix it for real.
I didn't want to use a purely 3d solution of clipping one portal polygon to another, as they could become non-convex ( imagine a triangular piece of a portal seend through a square portal ), so I wanted to maintain the 2d bounding rect method of intersection, but the fact that I wasn't updating the z extents of the view frusta was causing the portal system to get into loops.
Earlier methods of tagging portals with frame counters or putting them in sets didn't work b/c you can end up going through one portal to another portal more than once per frame ( again the case of multiple portals leading to one room ).
The solution was a hybrid - we use the same code the anti-portals use to construct a 3d frustum from the plane of the portal as the near plane, and the sides from the eye point and the portal edges. This frustum is used to reject other portals that don't cross it. The fact that the frustum near plane is the portal itself prevents the traversal from going backwards in an infinite loop. If we had mirrors or non-euclidean portals, we would need another scheme. If the new portal is not rejected, it is converted to 2d as before for intersection.
This series of fixes seems to have finally done the job, and we aren't able to get any of the previously failing cases to do anything strange.
I also fixed the fog culling issue - I was using the world bounds for the entities instead of the visual bounds for the fog culling step, which rarely caused a mismatch.