starting line 357 of g_reaction.c:
So yeah, this can explain everything,
/* Change active team for this shot only. */
team = level.activeTeam;
level.activeTeam = ent->team;
/* take the shot */
tookShot = G_ReactionFireShoot(G_PLAYER_FROM_ENT(ent), ent, ent->reactionTarget->pos, ST_RIGHT_REACTION, ent->chr.RFmode.fmIdx);
/* Revert active team. */
level.activeTeam = team;
Now, every 10 serverFrames, the AI code checks to find an actor to move like this:
if (level.framenum % 10)
return;
/* set players to ai players and cycle over all of them */
for (i = 0, player = game.players + game.sv_maxplayersperteam; i < game.sv_maxplayersperteam; i++, player++)
if (player->inuse && G_IsAIPlayer(player) && level.activeTeam == player->pers.team) {
if the AI thread interrupts the thread running the RF while it's taking a RF shot (assuming they are on different threads), then the activeTeam check is true, and I'm assuming the same goes for player->inuse. That will get the AI going. Now, IF all the aliens have next to 0 tu's, and given that the 2.3/current-trunk AI is quite fast, it will call for 'end of turn' once the for loop completes. It depends on the thread interleaving and that's why it's so hard to reproduce.
This is especially visible in my modified AI where it's execution time is currently very lengthy. RF[interrupted]->AI-start[interrupted]->RF[completes]->AI resumes thinking it's his turn. At this point it will try to make the alien shoot and the 'it's not your turn' will start swamping the log.
If this is really the problem, locking access to level or level.activeTeam while RF shooting should be enough (I have no idea how to do that). If there's a way for the AI to make sure RF is not going on at any given point, tell what to check for and I can fix this from the AI side.
UPDATE: Confirming that some kind of end of turn can be caused because of the RF & access to the level.activeTeam. I killed the AI by making it call end of turn as soon as it's about to start thinking for one of the aliens. Loaded up an open-space map and tried to move my squaddies. Result:
Team 1 ended round
Team 0's round started!
Team 0 ended round
Team 1's round started!
x12 !!!
And that's from a simple 20-TU walk in front of an alien. Notice that there's NO team 7 mentioned anywhere in there. Strange.
After moving around a little bit more and getting shot enough, the following strange occasion happened:
My squaddie "died" to RF getting the death animation, then promptly got up again, followed by crash with:
"ufo: src/client/battlescape/cl_actor.c:1779: CL_AddTargetingBox: Assertion `chr' failed."
This is different from all the other RF-related crashes I got, it's a different one every time. This is quite an important bug and we should get to it asap.
Unfortunately I have no idea how to mutex things.