PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Friday, August 5, 2022

[FIXED] How to use reraise in async workflows in F#?

 August 05, 2022     asynchronous, exception-handling, f#, f#-async     No comments   

Issue

I needed to reraise an exception that occurs while executing an async block, after logging the exception.

When I do the following the compiler thinks that I am not calling the reraise function from within the handler. What am I doing wrong?

let executeAsync context = async {
    traceContext.Properties.Add("CorrelationId", context.CorrelationId)
    try
        do! runAsync context
        return None
    with
        | e when isCriticalException(e) ->
            logCriticalException e
            reraise()
        | e ->
            logException e
            return Some(e)
}

Solution

Rough! I think this is impossible, because reraise corresponds to a special IL instruction that grabs the exception from the top of the stack, but the way async expressions are compiled into a chain of continuations, I don't think the semantics hold!

For the same reason, the following won't compile either:

try
    (null:string).ToString()
with e ->
    (fun () -> reraise())()

In these situations, where I need to handle the exception outside of the actual with body, and would like to emulate reraise (that is, preserve the stack trace of the exception), I use this solution, so all together your code would look like:

let inline reraisePreserveStackTrace (e:Exception) =
    let remoteStackTraceString = typeof<exn>.GetField("_remoteStackTraceString", BindingFlags.Instance ||| BindingFlags.NonPublic);
    remoteStackTraceString.SetValue(e, e.StackTrace + Environment.NewLine);
    raise e

let executeAsync context = async {
    traceContext.Properties.Add("CorrelationId", context.CorrelationId)
    try
        do! runAsync context
        return None
    with
        | e when isCriticalException(e) ->
            logCriticalException e
            reraisePreserveStackTrace e
        | e ->
            logException e
            return Some(e)
}

Update: .NET 4.5 introduced ExceptionDispatchInfo which may allow a cleaner implementation of reraisePreserveStackTrace above.



Answered By - Stephen Swensen
Answer Checked By - David Marino (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home
View mobile version

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing