As far as I understand it, the difference lies in how the routines handle pre-emption: do they abandon the earlier calls, or do they try to (eventually) service all requests? This is also tangled up with how triggers are addressed: Are they queued, or are they taken immediately? Hardware IRQ is usually done the latter (though the interrupts can be queued in hardware) but by contrast Windows message handling is mostly the former. An IRQ routine must decide whether it allows itself to be pre-empted with additional calls or not. Code hanging off a traditional Windows message loop doesn't have that concern: there are well defined points where the message-handler can get called and that isn't usually from within the handler itself.
You mentioned runaway triggers. If that's possible, the design should think of that and have some defenses in place. Referring back to the Windows message loop again; certain types of frequent messages (mouse updates are the canonical example, IIRC) are co-alesced into fewer messages by the queue handler. This means your message handler doesn't get bombarded by out-of-date mouse movements that it can't handle fast enough. Then, too, this is largely possible because the message handler must usually complete and exit before Windows will hand it another message to process.
Tackling trigger/message flooding is not really the same as bounding recursion.
Wade.