Here is one I had to track down recently.
The code in the following activity is trivial, but FaultyActivity represents any activity that might throw an exception during Execute and overrides HandleFault (which the WF runtime will schedule to run when it catches the exception tossed up by Execute).
The problem is that once an activity enters the Faulting state, it can only transition to Closed or back to Faulting. If another exception escapes during fault handling, the activity transitions back into the Faulting state, and WF schedules HandleFault to execute again - it’s an infinite loop if the exception continues to occur.
Adding some tracing to the app config file..
.. confirms the problem (abridged version):
Activity Status Change - Activity: faultyActivity1 Old:Initialized; New:Executing
Scheduling entry: ActivityOperation((1)faultyActivity1, Execute)
Execute of Activity faultyActivity1 threw System.InvalidOperationException
Activity Status Change - Activity: faultyActivity1 Old:Executing; New:Faulting
Scheduling entry: ActivityOperation((1)faultyActivity1, HandleFault)
Compensate of Activity faultyActivity1 threw System.InvalidOperationException
Activity Status Change - Activity: faultyActivity1 Old:Faulting; New:Faulting
Scheduling entry: ActivityOperation((1)faultyActivity1, HandleFault)
Compensate of Activity faultyActivity1 threw System.InvalidOperationException
Activity Status Change - Activity: faultyActivity1 Old:Faulting; New:Faulting
Scheduling entry: ActivityOperation((1)faultyActivity1, HandleFault)
Compensate of Activity faultyActivity1 threw System.InvalidOperationException ...
The sinister aspect to this behavior is that if enough workflows get into the infinite faulting loop, the threadpool becomes starved and the entire application just sits and spins with no work getting done.
Moral of the story – never let an exception escape from HandleFault.