If A_GunFlash was called from a weapon during iteration in P_MovePsprites (advancing all the overlays) it will process once when called, and once when the iterator reaches it, making it process two times within a single tick. The attached zip-file is a functional wad containing a weapon (FLASHWEAPON) you can give yourself to see some A_Log messages revealing the flow.
Weapon/flash flow on the tick when A_GunFlash is called.
(movepsprite-setpsprite) Weapon shows a log message (A_Log)
(movepsprite-setpsprite) Weapon launches a flash
(movepsprite-A_GunFlash-setpsprite) Flash shows a log message
(movepsprite-A_GunFlash-setpsprite) Flash encounters a > 0 duration and ends processing
(movepsprite) Weapon encounters a > 0 duration and ends processing
(movepsprite-setpsprite) Flash resumes processing and shows a log message (A_Log)
(movepsprite) Flash ends
The above does not occur if A_GunFlash is triggered by BT_ATTACK during regular input processing, because that input test is performed after all psprites have been moved. This means that the weapon will first process whatever state it is on, and then process fire/altfire, leaving it in a feasible state, having processed only a single tick of fire. Because we're past the iteration, the iterator does not act on any flash states that have been set and processed during the first tick of the firing state.
A_ReFire triggers an input-based firing state during the processing phase in which it was encountered (typically/always weapon processing).
Spoiler: tick scenarios
Spoiler: A_GunFlash after 0 tics
tick 1:
processing weapon, weapon enters ready state (this tick); it can fire
processing flash has no work
weapon is ready and BT_ATTACK is held (weapon fires, processes 1 tick)
A_GunFlash, flash is set and processed (1 tick)
this situation is rendered
tick 2...X: weapon / flash render together
tick Y:
processing weapon, weapon calls A_Refire and BT_ATTACK is held
-- fire state set and processed (1 tick), A_GunFlash is called
-- flash is set and processed (1 tick)
processing flash (1 tick)
weapon is firing, input not relevant
flash has processed twice (!)
this situation is rendered
Spoiler: A_GunFlash after 1 ticks (or more)
tick 1:
processing weapon, weapon is ready
processing flash (no flash)
weapon is ready and BT_ATTACK is held (weapon fires, processes 1 tick)
this situation is rendered
tick 2:
processing weapon (in firing state), A_GunFlash is called
-- flash is set and processed (1 tick)
processing flash (1 tick)
weapon is firing, input not relevant
flash has processed twice (!)
I'm just bumping this to say that this kind of 'fix' is always causing more problems than it solves, especially when nobody bothers to investigate the consequences.