Enhance try/catch to support retries. #532
Replies: 14 comments
-
Related / duplicate(?): #127 |
Beta Was this translation helpful? Give feedback.
-
@Korporal The CLR abstracts exception handling pretty far away from the details of Win32. However that abstraction is quite flexible and does allow for exactly what you're describing. In fact, VB.NET already supports it via However, I will argue that such exception handling is anything except structured. The resulting code is much more difficult to follow. |
Beta Was this translation helpful? Give feedback.
-
How much code would be run again when If it's just the throwing IL instruction, then I don't think this would be useful, since that instruction would almost always be |
Beta Was this translation helpful? Give feedback.
-
@svick - #127 is certainly related. My position is that we should be able to implement that example in managed code, that's the origin of the problem for me anyway. My work (back then) required threads to fault when trying to write to shared memory pages that were set as read-only. This required certain actions be performed and the page's access being reset to read-write, I won't bore you with the details but it was impossible to code this in managed so I added it to a native API we were using. Perhaps a way forward would not be a "retry" but rather an "resolve" block, akin to a "catch" block:
The class ResolvableException would contain members that indicate the nature of the exception (akin to the way Win32 does stuff) but in a platform agnostic manner. |
Beta Was this translation helpful? Give feedback.
-
@Korporal How does a And I don't know much about SEH, but couldn't you PInvoke something like |
Beta Was this translation helpful? Give feedback.
-
@svick - The difference in my mind is simply that "resolve" is dedicated to handling retriable operations. It would (under the hood) handle the returning of the continuation code (in the case of Windows anyway) EXCEPTION_CONTINUE_EXECUTION. That's how SEH does it, it's the handler that decides whether to continue so having a "resolve" block kind of mirrors that. You may well be right, yes the origin of this was a specific situation but perhaps there's a larger scope of problems that this kind of thing could be applicable too. It's been like 6 years since I even looked at the code that manages this (native code) so I can't recall the details or whether it could be exposed in some way (I guess we could have a native handler callback into a managed handler - a delegate but I'd need to spend time looking at this). |
Beta Was this translation helpful? Give feedback.
-
Why not use recursion? The introduction of local functions and exception filters make this rather simple to write. If stack space is exhausted due to recursive retries, something else is likely wrong with the code anyway. void DoSomething()
{
int maxRetries = 4, retryCount = 0;
trySomething();
void trySomething()
{
try
{
throw new Exception(retryCount.ToString());
}
catch when (++retryCount < maxRetries)
{
trySomething();
}
}
} |
Beta Was this translation helpful? Give feedback.
-
Seems more complex to think about than a loop. |
Beta Was this translation helpful? Give feedback.
-
That's true, I guess I generally prefer recursion to loops when the increment or conditional cannot be written in the loop header. Speaking of, it would be nice to have a |
Beta Was this translation helpful? Give feedback.
-
I know, I keep thinking the same about |
Beta Was this translation helpful? Give feedback.
-
Yeah and I don't know which one I like less. |
Beta Was this translation helpful? Give feedback.
-
I just want to point out that the native SEH for this is fundamentally able to retry the very machine instruction that raised the exception. There is nothing like this in managed code to my knowledge. @svick has mentioned installing a handler, and I think this could be done. We could install a retriable handler from managed code that would return the retry opcode (just an ineteger). |
Beta Was this translation helpful? Give feedback.
-
@aluanhaddad - In your "recursive" example you overlook the core nature of the EXCEPTION_CONTINUE_EXECUTION mechanism in native code. This operation causes the actual machine instruction that caused the exception to be retried, the CPU instruction pointer is forcibly reset to the address of that instruction. This is the basis of how Windows (and others) implement page fault handling. I've often longed for C# to embrace a few more mechanisms like this so that it could be a contender for a true systems programming language, currently to write the kind of this I allude to one MUST write native code and use interop from C#. Recent progress with generic constraint |
Beta Was this translation helpful? Give feedback.
-
Imagine for a moment that you wanted to implement this wholly in C#. We can't because there is no way to perform EXCEPTION_CONTINUE_EXECUTION in C#. This is what this suggestion is about, enabling C# to be used for these kinds of scenarios. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
The OS (and I presume the CLR leverages this) exposes structured exception handling via well know API. In that API set is the signature for the callback VectoredHandler which returns a long int. One of the values supported is EXCEPTION_CONTINUE_EXECUTION which means that execution should resume at the instruction that originally caused the original exception. This mechanism is used (for example) to underpin the management of page fault handling.
I've used this myself on several native Win32 APIs and there are several examples of its utility too.
So my question/suggestion is to consider adding this to the C# try/catch mechanism, perhaps via new keyword "retry". This would allow us to code stuff similar to the above example, but in managed code.
The keyword "retry" could only appear within a "catch" block and would cause re-execution of the IL that originally caused the exception, there may well be restrictions too so one must "catch" specific defined exceptions in order for "retry" to be permitted (or perhaps the exception class has to have some new attribute "Retriable").
I asked this on a MS forum around a decade ago and wondered if things have moved on enough for this to be seriously considered - like I said, imagine the task was to write a C# version of the sample code cited above...
Beta Was this translation helpful? Give feedback.
All reactions