ISRs are called with the main line code in any sort of state, running any sort of routine. A null ISR must at the very least execute a return with all program parameters restored intact so the main line code is not corrupted. A well written ISR will be invoked transparently. Destroy a register, and the code will eventually crash. The initial register push must include every register that will be used by the ISR - including the flag bits.
Some processors do push the flags automatically.
The only reason the ISR was called was to service interrupting hardware. This action takes an infinite variety of forms. The biggest mistake made in ISRs, though, is to put too much hardware service in the ISR itself. Simple interrupts, like UART handlers, basically queue up or dequeue data in just a few lines of code. A valid interrupt-phobia is that they are a bit more difficult to debug than conventional code.