Handling long running, blocking functions - ada

In a project I have to use an imported C function that sends a request to a server and receives a response. It is possible to provide a timeout parameter to this function to specify the maximum time before the blocking function returns if the server is not reachable.
Unfortunately this timeout is not always reliable and often the maxium timeout value is exceeded. What is the best Ada approach to handle this kind of problem?
After reading this chapter I am not sure if I could use this kind of programming pattern? The imported C function is not thread safe so only one request at a time is possible. A perfect solution would allow one to send a request (with a valid response or the timeout response normally returned by the imported C function) and a second function could be used to query if the last request timed out. Until the imported C function call has returned further requests should always return the timout response.
I am not sure what happens to the entries (programming statements inside the entries) Password_Server.Set and Process_Data.Output call if the delay alternative is chosen?

If the entry call is queued or waiting for access to a protected object (PO), then the entry call is aborted when the delay expires, the delay branch is executed, and the select finishes. If the entry call has been accepted (task) or is executing (PO) when the delay expires, it continues until it finishes or is requeued. If it finishes, then the entry branch is executed and the select finishes. If it is requeued with abort it behaves just as it does initially. If it is requeued without abort, then the delay branch is ignored. (Note that if it's requeued without abort, it can still be later requeued with abort, so things can be more complicated. It's best to try to avoid such a design.)
IIUC correctly, you want only one task at a time to be able to call the C operation. If one task is calling it and another tries to, the second task should be told the call timed out. Ada should abort the C operation if it takes longer than its timeout.
The only way I can see to abort the call to C is with an Asynchronous Transfer of Control. Whether that will actually do what is wanted is an open question.
This leads me to something like
package Calling_C is
type Data is ...
procedure Call_C (Info : in Data; Timeout : in Duration; Timed_Out : out Boolean);
end Calling_C;
package body Calling_C is
task Control is
entry Call_C (Info : in Data; Timeout : in Duration; Timed_Out : out Boolean);
end Control;
task body Control is
begin
Forever : loop
select
accept Call_C (Info : in Data; Timeout : in Duration; Timed_Out : out Boolean) do
select
delay Timeout;
Timed_Out := True;
then abort
-- Call the C operation
end select;
end Call_C;
or
terminate;
end select;
end loop Forever;
end Control;
procedure Call_C (Info : in Data; Timeout : in Duration; Timed_Out : out Boolean) is
begin
select
Control.Call_C (Info => Info, Timeout => Timeout, Timed_Out => Timed_Out);
else
Timed_Out := True;
end Select;
end Call_C;
end Calling_C;
The first task gets in and calls the C operation. Subsequent tasks are not accepted immediately and return with Timed_Out set to True. If the call to C doesn't return in time, maybe it's aborted.

I don't actually know Ada very good just yet. Posting my idea here so pros can tell me whether it's a bad idea. The server would look something like this:
task Server is
entry Request (in Input : Input_Type);
entry Response (out Output : Output_Type);
end Server;
task body Server is
Local_Input : Input_Type;
Local_Output : Output_Type;
begin
accept Request (Input : in Input_Type) do
Local_Input := Input;
end Request;
Local_Output := My_C_Code(Local_Input);
accept Response(Output : out Output_Type) do
Output := Local_Output;
end Response;
end Server;
How to use it:
Server.Request(Input);
select
Server.Response(Output);
-- got your response
or
delay Timeout;
-- response timeout
end select;
As you may have realized the Server will block on Response until the Request caller (or anyone else) decides to call it. My best guess is either a) adding select ... or terminate, or b) handle the timeout and go back to waiting for Response, sync or async.

Related

akka grpc server stream cannot return every result in real time

First of all, I have a server stream method. In the method, I will request an actor in a loop. I expect that after each request is responded, the application will return the result to the caller. But no, I found that it still waits for all responses to be completed before returning, is this normal?
// The code is as follows, for the convenience of observing the results, I added sleep
override def itKeepsReplying(in: HelloRequest): Source[HelloReply, NotUsed] = {
Source(1 to 10).map(index => {
Thread.sleep(5000)
HelloReply(character.toString)
})
}
In order to confirm whether grpc itself supports, I tried java's implementation of this piece,
If you want to send data to the caller: responseObserver.onNext(responseBuilder.build());,
If you want to end this call: responseObserver.onCompleted(); ,
Data is sent to the caller every time onNext is called.
So my question is:
Is my assumption correct? If akka-grpc can do it
If it can be done, please give an example

how to implement a non-blocking server in Ada?

My current design looks like this
task body Agent_Task is
begin
loop
select
accept Request_A do
end Request_A;
or
accept Request_B do
end Request_B;
or
...
else
Do_Other_Stuff;
end select;
end loop;
exception
when Exception_Id : others => Show_Exception (Exception_Id);
end Agent_Task;
But when calling an entry in an agent frequently (e.g. Request_A) it will become non-responsive.
Is there a better structure to make the agent never be blocked? like interrupts?
The most time consuming part is in Do_Other_Stuff, what I want the server to do is roughly:
loop
Do_Other_Stuff;
if interrupted, handle other requests.
end loop;
This a school assn which I can not modify the test program to retry a failed request to an agent. When the test is runing, mutilple agents will talk to each other concurrently.
Note that you have a spurious end; in your code that makes it illegal.
If what's important is that those making requests not block, you could use a protected queue for the inter-task communication:
loop
select
Request_Queue.Get (Item => Request);
Process (Request => Request);
else
Do_Other_Stuff;
end select;
end loop;
Requests will not be processed until Do_Other_Stuff completes, but those making requests will not be blocked by putting a request on the queue.
Using a queue would also allow you to use asynchronous transfer of control to give requests priority over Do_Other_Stuff:
loop
select
Request_Queue.Get (Item => Request);
Process (Request => Request);
then abort
Do_Other_Stuff;
end select;
end loop;
Do_Other_Stuff would then need to be abortable, and able to pick up from where it left off the next time it runs. But it would be better if Do_Other_Stuff could be moved into another task as Holsti suggested.
Finally, if you can't move Do_Other_Stuff to another task, and you can't abort it, you may need to break it into shorter parts:
loop
Do_Some_Stuff;
Handle_Requests;
Do_Some_More_Stuff;
Handle_Requests;
..
end loop;
Again, this is easier with a queue, since accept statements can't go in a subprogram.
Move the Do_Other_Stuff to another task, that is, divide your Agent_Task into two tasks.
How difficult that is depends on how much communication (data flow) there is between Do_Other_Stuff and the actions for Request_A and Request_B. If Do_Other_Stuff is moved to its own task, that task has to communicate with the original Agent_Task is some way, by rendez-vous or protected objects. If Do_Other_Stuff is a long computation that has some inputs and some outputs, you might add two entries to Agent_Task, one to provide the inputs to the Other_Stuff task, and another to receive the outputs from the Other_Stuff task.

Webhook process run on another goroutine

I want to run some slow routine in another goroutine, is it safe to do it like this:
func someHandler(w http.ResponseWriter, r *http.Request) {
go someReallySlowFunction() // sending mail or something slow
fmt.Fprintf(w,"Mail will be delivered shortly..")
}
func otherHandler(w http.ResponseWriter, r *http.Request) {
foo := int64(0)
bar := func() {
// do slow things with foo
}
go bar()
fmt.Fprintf(w,"Mail will be delivered shortly..")
}
Is there any gotchas by doing this?
Serving each http request runs in its own goroutine (more details on this). You are allowed to start new goroutines from your handler, and they will run concurrently, independently from the goroutine executing the handler.
Some things to look out for:
The new goroutine runs independently from the handler goroutine. This means it may complete before or after the handler goroutine, you cannot (should not) assume anything regarding to this without explicit synchronization.
The http.ResponseWriter and http.Request arguments of the handler are only valid and safe to use until the handler returns! These values (or "parts" of them) may be reused - this is an implementation detail of which you should also not assume anything. Once the handler returns, you should not touch (not even read) these values.
Once the handler returns, the response is committed (or may be committed at any moment). Which means your new goroutine should not attempt to send back any data using the http.ResponseWriter after this. This is true to the extent that even if you don't touch the http.ResponseWriter in your handler, not panicing from the handler is taken as a successful handling of the request and thus HTTP 200 status is sent back (see an example of this).
You are allowed to pass the http.Request and http.ResponseWriter values to other functions and to new goroutines, but care must be taken: you should use explicit synchronization (e.g. locks, channels) if you intend to read / modify these values from multiple goroutines (or you want to send back data from multiple goroutines).
Note that seemingly if both your handler goroutine and your new goroutine just reads / inspects the http.Request, that still may be problematic. Yes, multiple goroutines can read the same variable without synchronization (if nobody modifies it). But calling certain methods of http.Request also modify the http.Request, and without synchronization there is no guarantee what other goroutines would see from this change. For example Request.FormValue() returns a form value associated with the given key. But this method calls ParseMultiPartForm() and ParseForm() if necessary which modify the http.Request (e.g. they set the Request.PostForm and Request.Form struct fields).
So unless you synchronize your goroutines, you should not pass Request and ResponseWriter to the new goroutine, but acquire data needed from the Request in the handler goroutine, and pass only e.g. a struct holding the needed data.
Your second example:
foo := int64(0)
bar := func() {
// do slow things with foo
}
go bar()
This is perfectly fine. This is a closure, and local variables referred by it will survive as long as they are accessible.
Note that alternatively you could pass the value of the local variable to the anonymous function call as an argument like this:
foo := int64(0)
bar := func(foo int64) {
// do slow things with param foo (not the local foo var)
}
go bar(foo)
In this example the anonymous function will see and use its parameter foo and not the local variable foo. This may or may not be what you want (depending on whether the handler also uses the foo and whether changes made by any of the goroutines need to be visible to the other - but that would require synchronization anyway, which would be superseded by a channel solution).
If you care for acknowledgement for the mail, then the posted code won't help. Running the code in separate goroutine makes it independent and the server reply will be success even if the mail is not sent due to some error in the goroutine function.

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.

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

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).

Resources