F# Async.FromBeginEnd calling End function when it shouldn't? - asynchronous

I am doing some low level socket work using F# and am making everything asynchronous. I have a socket that I am using to listen for connections using an async workflow to handle them so it is using this to wrap the Socket.BeginListen() and Socket.EndListen().
member socket.AsyncAccept () =
Async.FromBeginEnd( socket.BeginAccept, endOrDisposed socket.EndAccept null )
When I want to stop listening, at the moment I am doing a Socket.Close() on it which will cause the async operation started by Socket.BeginAccept() to complete.
Originally I then ran into a problem as the FromBeginEnd() function would always call the EndXXX() function no matter how the operation started by BeginXXX() completed. In some cases this would lead to an ObjectDisposed exception by the EndXXX() function as by the time it was called the Socket had been closed and disposed. I added a little handler function which would filter those exceptions out thus:
let endOrDisposed endFunc defaultResult iar = try endFunc iar with | _ -> defaultResult
This does the trick, but not when running in debug. I am well aware that the Just My Code option can be used to hide the exception but this could be happening with some other IO operations on a more frequent basis so I also would rather not have processor time wasted on raising and catching exceptions which shouldn't really be there in the first place. Also I might not want to hide where other exceptions are being thrown as they could by in areas where I do need to debug.
I've looked at the code for Async.FromBeginEnd and it is wired to always call the EndXXX() function no matter what, I'm not sure this is the best behaviour, perhaps I should write a replacement for it? Or does anyone have any other ideas for elegant solutions?
I just found (sure I'd looked before though) this in the docs:
To cancel a pending call to the BeginAccept() method, close the
Socket. When the Close() method is called while an asynchronous
operation is in progress, the callback provided to the BeginAccept()
method is called. A subsequent call to the EndAccept() method will
throw an ObjectDisposedException to indicate that the operation has
been cancelled.
I still don't like the exception, even if it is by design. I'd prefer to find a way to not call EndXXX() on a disposed object. Perhaps I can mix some CancellationToken magic into this somehow?

I would make use of the optional cancelAction argument to Async.FromBeginEnd here:
type Socket with
member this.AsyncAccept () =
let canceled = ref false
let endAccept iar = if not !canceled then this.EndAccept iar else null
let cancel () = canceled := true; this.Close ()
Async.FromBeginEnd (this.BeginAccept, endAccept, cancelAction = cancel)
This way you can use Async's builtin cancellation functionality (which is of course based on CancellationToken) without touching a CancellationToken directly. (I.e., you should not be calling Socket.Close for cancellation purposes.)

What's needed is a method to interrupt the Async.FromBeginEnd process and stop it trying to EndAccept in the case where the socket is being closed (this probably extends to other operations besides Accept).
Instead of having calls to Socket.Close() I used a CancellationTokenSource and registered a handler with it which will call Socket.Close():
cts.Token.Register (fun () -> listener.Close()) |> ignore
and then instead of passing Async.FromBeginEnd the EndAccept function directly it now goes via a function that will stop the EndAccept being called if the token has been cancelled.
let endOrDisposed endFunc defaultResult iar = try endFunc iar with | _ -> defaultResult
let endIfNotCancelled endFunc defaultResult (token:CancellationToken) iar = if token.IsCancellationRequested then defaultResult else endOrDisposed endFunc defaultResult iar
type Socket with
member socket.AsyncAccept (cancelToken) =
Async.FromBeginEnd( socket.BeginAccept, endIfNotCancelled socket.EndAccept null cancelToken)
This still uses my function to filter out and ignore exceptions (I don't think exceptions are very exceptional when it comes to networking, and in this apps case there is nothing it would do in response anyway).

Related

How to make async function yield on block?

I just started learning asynchronous Rust, so this is propably not a difficult question to answer, however, I am scratching my head here.
I am not trying to run tasks in parallel yet, only trying to get them to run concurrently.
According to the guide at https://rust-lang.github.io/async-book/,
The futures::join macro makes it possible to wait for multiple different futures to complete while executing them all concurrently.
So when I create 2 Futures, I should be able to "await" both of them at once. It also states that
Whereas calling a blocking function in a synchronous method would block the whole thread, blocked Futures will yield control of the thread, allowing other Futures to run.
From what I understand here, if I await multiple Futures with join!, should the first one be blocked, the second one will start running.
So I made a very simple example where I created 2 async fns and tried to join! both, making sure the first one gets blocked. I used a mpsc::channel for the blocking, since the docs stated that thread::sleep() should not be used in async fns and that recv()
will always block the current thread if there is no data available
However, the behavior is not what I expected, as calling the blocking function will not yield control of the thread, allowing the other Future to run, like I would expect from the second quote I provided. Instead, it will just wait untill it is no longer blocked, finish the first Future and only then start the second. Pretty much as if they were synchronous and I would have just called one after the other.
My complete example code:
use std::{thread::{self}, sync::{mpsc::{self, Sender, Receiver}}, time::Duration};
use futures::{executor}; //added futures = "0.3" in cargo.toml dependencies
fn main(){
let fut = main_async();
executor::block_on(fut);
}
async fn main_async(){
let (sender, receiver) = mpsc::channel();
let thread_handle = std::thread::spawn(move || { //this thread is just here so the f1 function gets blocked by something and can later resume
wait_send_function(sender);
});
let f1 = f1(receiver);
let f2 = f2();
futures::join!(f1, f2);
thread_handle.join().unwrap();
}
fn wait_send_function(sender: Sender<i32>){
thread::sleep(Duration::from_millis(5000));
sender.send(1234).unwrap();
}
async fn f1(receiver: Receiver<i32>){
println!("starting f1");
let new_nmbr = receiver.recv().unwrap(); //I would expect f2 to start now, since this is blocking
println!("Received nmbr is: {}", new_nmbr);
}
async fn f2(){
println!("starting f2");
}
And the output is simply:
starting f1
Received nmbr is: 1234
starting f2
My question is what am I missing here, why does f2 only start after f1 is completed and what would I need to do to get the behavior I want (completing f2 first if f1 is blocked and then waiting for f1)?
Maybe the book is a little misleading, but when it refers to "a blocked future", it does not mean in the sense of blocking synchronous code (if that was the case, there would be no problem to use std::thread::sleep()), but rather, it means that the future is waiting to be polled by the executor.
Thus, std::mpsc that blocks the thread will not have the desired effect (definitely not on a single-threaded executor like future's, but it's a bad idea on multi-threaded executors too). Use futures::channel::mpsc and everything will work.

Why Async.StartChild does not take CancellationToken?

I am struggling to understand Async.[StartChild|Start] API design.
What I would like is to start an async process which does some tcp stream reading and calling a callback according to commands arriving on tcp.
As this async process does not really return any single value, it seems like I should use Async.Start. At some point I want to "close" my tcp client and `Async.Start takes CancellationToken, which gives me ability to implement 'close". So far so good.
The problem is, I would like to know when tcp client is done with cancellation. There is some buffer flushing work done, once Cancel is requested, so I do not want to terminate application before tcp client is done cleanup. But Async.Start returns unit, which means I have no way of knowing when such async process is complete. So, looks like Async.StartChild should help. I should be able to invoke cancellation, and when cleanup is done, this async will invoke next contiuation in chain (or throw an exception?). But... Async.StartChild does not take CancellationToken, only timeout.
Why Async.StartChild implements just single case of cancellation strategy (timeout) instead of exposing more generic way (accept CancellationToken)?
To answer the first part of the question - if you need to do some cleanup work, you can just put it in finally and it will be called when the workflow is cancelled. For example:
let work =
async {
try
printfn "first work"
do! Async.Sleep 1000
printfn "second work"
finally
printfn "cleanup" }
Say you run this using Async.Start, wait for 500ms and then cancel the computation:
let cts = new System.Threading.CancellationTokenSource()
Async.Start(work, cts.Token)
System.Threading.Thread.Sleep(500)
cts.Cancel()
The output will be "first work, cleanup". As you can see, cancelling the computation will run all the finally clauses.
To answer the second part of the question - if you need to wait until the work completes, you can use RunSynchronously (but then, perhaps you do not actually need asynchronous workflows, if you are blocking anyway...).
The following starts a background process that cancels the main work after 500ms and then starts the main work synchronously:
let cts = new System.Threading.CancellationTokenSource()
async {
do! Async.Sleep(500)
cts.Cancel() } |> Async.Start
try Async.RunSynchronously(work, cancellationToken=cts.Token)
with :? System.OperationCanceledException -> ()
printfn "completed"
This prints "first work, cleanup, completed" - as you can see, the RunSynchronously call was blocked until the work was cancelled.

F# Async File Copy

To copy a file asynchronously, will something like this work?
let filecopyasync (source, target) =
let task = Task.Run((fun () ->File.Copy(source, target, true)))
// do other stuff
Async.AwaitIAsyncResult task
In particular, will this fire up a new thread to do the copy while I "do other stuff"?
UPDATE:
Found another solution:
let asyncFileCopy (source, target, overwrite) =
printfn "Copying %s to %s" source target
let fn = new Func<string * string * bool, unit>(File.Copy)
Async.FromBeginEnd((source, target, overwrite), fn.BeginInvoke, fn.EndInvoke)
let copyfile1 = asyncFileCopy("file1", "file2", true)
let copyfile2 = asyncFileCopy("file3", "file4", true)
[copyfile1; copyfile2] |> seq |> Async.Parallel |> Async.RunSynchronously |> ignore
Your question is conflating two issues, namely multithreading and asychrony. It's important to realise that these things are entirely different concepts:
Asychrony is about a workflow of tasks where we respond to the completion of those tasks independently of the main program flow.
Multithreading is an execution model, one which can be used to implement asychrony, although asychrony can be acheived in other ways (such as hardware interrupts).
Now, when it comes to I/O, the question you should not be asking is "Can I spin up another thread to do it for me?"
Why, you ask?
If you do some I/O in the main thread, you typically block the main thread waiting for results. If you evade this problem by creating a new thread, you haven't actually solved the issue, you've just moved it around. Now you've blocked either a new thread that you've created or a thread pool thread. Oh dear, same problem.
Threads are an expensive and valuable resources and shouldn't be squandered on waiting for blocking I/O to complete.
So, what is the real solution?
Well, we achieve asynchrony via one of these other approaches. That way, we can request that the OS perform some I/O and request that it let us know when the I/O operation is complete. That way, the thread is not blocked while we're waiting for results. In Windows, this is implemented via something called I/O completion ports.
How do I do this in F#?
The .NET CopyToAsync method is probably the easiest approach. Since this returns a plain task, it's helpful to create a helper method:
type Async with
static member AwaitPlainTask (task : Task) =
task.ContinueWith(ignore) |> Async.AwaitTask
Then
[<Literal>]
let DEFAULT_BUFFER_SIZE = 4096
let copyToAsync source dest =
async {
use sourceFile = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.Read, DEFAULT_BUFFER_SIZE, true);
use destFile = new FileStream(dest, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, DEFAULT_BUFFER_SIZE, true);
do! sourceFile.CopyToAsync(destFile) |> Async.AwaitPlainTask
}
You could then use this with Async.Parallel to perform multiple copies concurrently.
Note: This is different to what you wrote above because File.Copy is a sychronous method that returns unit while CopyToAsync is an async method that returns Task. You cannot magically make synchronous methods asychronous by putting async wrappers around them, instead you need to make sure you are using async all the way down.
You can test it yourself with a few printfns. I found I had to RunAsynchronously to force the main thread to wait for the copy to complete. I'm not sure why the await didn't work, but you can see the expected set of outputs indicating that the copy happened in the background.
open System
open System.IO
open System.Threading
open System.Threading.Tasks
let filecopyasync (source, target) =
let task = Task.Run((fun () ->
printfn "CopyThread: %d" Thread.CurrentThread.ManagedThreadId;
Thread.Sleep(10000);
File.Copy(source, target, true); printfn "copydone"))
printfn "mainThread: %d" Thread.CurrentThread.ManagedThreadId;
let result=Async.AwaitIAsyncResult task
Thread.Sleep(3000)
printfn "doing stuff"
Async.RunSynchronously result
printfn "done"
Output:
filecopyasync (#"foo.txt",#"bar.txt");;
mainThread: 1
CopyThread: 7
doing stuff
copydone
done
If all you're trying to do is run something on another thread while you do something else, then your initial Task.Run approach should be fine (note that you can get a Task<unit> if you call Task.Run<_> instead of the non-generic Task.Run, which might be marginally easier to deal with).
However, you should be clear about your goals - arguably a "proper" asynchronous file copy wouldn't require a separate .NET thread (which is a relatively heavy-weight primitive) and would rely on operating system features like completion ports instead; since System.IO.File doesn't provide a native CopyAsync method you'd need to write your own (see https://stackoverflow.com/a/35467471/82959 for a simple C# implementation that would be easy to transliterate).

Resume execution at arbitrary positions inside a callback function

I am using Pin for dynamic analysis.
In my dynamic analysis task on 64-bit x86 binary code, I would like to resume the execution at arbitrary program positions (e.g., the second instruction of current executed function) after I fix certain memory access error inside the signal handling callbacks.
It would be something like this:
BOOL catchSignalSEGV(THREADID tid, INT32 sig, CONTEXT *ctx, BOOL hasHandler, const EXCEPTION_INFO *pExceptInfo, VOID *v)
{
// I will first fix the memory access error according to certain rules.
fix();
// then I would like to resume the execution at an arbitrary position, say, at the beginning of current monitored function
set_reg(rip, 0x123456); // set the rip register
PIN_ExecuteAt(ctx); // resume the execution
return false;
}
However, I got this exception: E: PIN_ExecuteAt() cannot be called from a callback.
I know I can resume the execution at "current instruction" by return false at the end of the signal handling function, but basically can I resume at arbitrary positions?
Am I clear? Thank you for your help!
The documentation is clear on this:
A tool can call this API to abandon the current analysis function and resume execution of the calling thread at a new application register state. Note that this API does not return back to the caller's analysis function.
This API can be called from an analysis function or a replacement routine, but not from a callback.
The signal handler is considered a callback. You can only use PIN_ExecuteAt in an analysis function or a replacement routine.
One thing you may try to do is to save the context you are interested in and allow the application to resume, ensuring that the next instruction to be executed has an analysis callback attached. You may be able to use if-then instrumentation to improve performance. Then you can call ExecuteAt from that analysis routine.

SignalR .Net client - how to invoke synchronously and asynchronously

I'm learning SignalR using the .Net client (not javascript), and was hoping for some clarification on how to invoke hub proxy methods in a synchronous or asynchronous manner.
Method with no return value
So far I've been doing something like this:-
myHubProxy.Invoke("DoSomething");
I've found this to be asynchronous, which is fine as it's effectively "fire-and-forget" and doesn't need to wait for a return value. A couple of questions though:-
Are there any implications with wrapping the Invoke in a try..catch block, particularly with it being asynchronous? I might want to know if the call failed.
Are there any scenarios where you would want to call a method that doesn't return a value synchronously? I've seen the .Wait() method mentioned, but I can't think why you would want to do this.
Method with return value
So far I've been using the Result property, e.g.:-
var returnValue = myHubProxy.Invoke<string>("DoSomething").Result;
Console.WriteLine(returnValue);
I'm assuming this works synchronously - after all, it couldn't proceed to the next line until a result had been returned. But how do I invoke such a method asynchronously? Is it possible to specify a callback method, or should I really be using async/await these days (something I confess to still not learning about)?
If you want to write asynchronous code, then you should use async/await. I have an intro on my blog with a number of followup resources at the end.
When you start an asynchronous operation (e.g., Invoke), then you get a task back. The Task type is used for asynchronous operations without a return value, and Task<T> is used for asynchronous operations with a return value. These task types can indicate to your code when the operation completes and whether it completed successfully or with error.
Although you can use Task.Wait and Task<T>.Result, I don't recommend them. For one, they wrap any exceptions in an AggregateException, which make your error handling code more cumbersome. It's far easier to use await, which does not do this wrapping. Similarly, you can register a callback using ContinueWith, but I don't recommend it; you need to understand a lot about task schedulers and whatnot to use it correctly. It's far easier to use await, which does the (most likely) correct thing by default.
The .Result property returns a async Task, so the server requests is still performed async.
There is not reason to hold up a thread for the duration of the call thats why you use async.
If you fire the call on the GUI thread its even more important todo it async because otherwise the GUI will not respond while the call is done
1) Yuo need to use the await keyword if you want try catch blocks to actually catch server faults. Like
try
{
var foo = await proxy.Invoke<string>("Bar");
}
catch (Exception ex)
{
//act on error
}
2) I think you ment to ask if its any reason to call it async? And yes like I said, you do not want to block any threads while the request is being made

Resources