Jump to content
chkaufmann

TIdHTTPServer.OnCommandGet - Timeout

Recommended Posts

I handle all requests in OnCommandGet. Sometimes these get blocked but I couldn't locate yet where and why. 

 

As a first solution I would like to cancel the command after a certain time. I found the TerminateWaitTime property, but since the value is never used in code I think this doesn't work. Is there another solution for this? Something like max_execution_time in PHP?

 

Christian

Share this post


Link to post
9 hours ago, chkaufmann said:

I handle all requests in OnCommandGet. Sometimes these get blocked but I couldn't locate yet where and why. 

Blocked in what way exactly?  Please provide more details about what exactly you are seeing happen.

 

Are you seeing blockage when receiving a request, sending a response, or something in between?

 

The OnCommand... event handler is not fired until after TIdHTTPServer has finished reading an entire request in full to populate the TIdHTTPRequestInfo object that gets passed to the OnCommand... handler.  A response is not sent back to the client until after the OnCommand... handler exits (unless you trigger the sending of the response manually using various TIdHTTPResponseInfo methods).

 

Any blockage in between receiving and sending would be in your processing.

9 hours ago, chkaufmann said:

As a first solution I would like to cancel the command after a certain time.

The only way to cancel an HTTP request that is in progress is to close the socket connection.

 

If the blockage is happening while receiving a request, consider setting a non-infinite timeout to the TIdContext.Connection.ReadTimeout property.  If the blockage is happening while sending a response, Indy does not implement write timeouts, but you can use the OS's underlying socket API manually to set one, if needed.

 

Any blockage in between receiving and sending would need to be handled in your own code.

9 hours ago, chkaufmann said:

I found the TerminateWaitTime property, but since the value is never used in code I think this doesn't work.

That property would not help you anyway.  It is deprecated and no longer used by Indy, but when it was, it was used only during server shutdown, to specify a timeout for waiting for individual server threads to terminate.  It was never used during request/response handling.

9 hours ago, chkaufmann said:

Something like max_execution_time in PHP?

There is nothing like that in Indy.  Such timeouts would have to be implemented in your own code.

Share this post


Link to post

I use "FHttpServer.Contexts.Count" for status information and it happens, that the counter doesn't go to zero. So I don't know, if it's during read/write or in my code.

 

So the first thing I have to do is to count in the OnCommandGet handler as well, so I know if it's in my code or not.

 

max_execution_time: If I would like to do something like that I would had to handle the request in another again probably? Something like a background worker from the Omnithread library? Then I can set a wait event and cancel execution after a certain amount of time.

Share this post


Link to post
23 hours ago, chkaufmann said:

I use "FHttpServer.Contexts.Count" for status information and it happens, that the counter doesn't go to zero.

That means either TCP connections are not being closed, or the threads that own them are not being terminated correctly (deadlocks, etc).

23 hours ago, chkaufmann said:

So I don't know, if it's during read/write or in my code.

Well, you need to debug your code and find out.

23 hours ago, chkaufmann said:

max_execution_time: If I would like to do something like that I would had to handle the request in another again probably? Something like a background worker from the Omnithread library? Then I can set a wait event and cancel execution after a certain amount of time.

Something like that, yes.

Share this post


Link to post

I still try to locate the problem. Right now I have the situation, that a request blocks all following request. So I want to cancel it as save as possible. In the main thread I know my TIdHTTPServer component and I know the TIdContext of the request I want to remove. What is the savest way to do it from "outside the request"?

Share this post


Link to post

Follow up question: I create my own request object in my OnCommandGet event. Is there a way to have a reference to this in the current TIdContext or do I have to build my own list/container for this?

 

Christian

Share this post


Link to post
14 hours ago, chkaufmann said:

I still try to locate the problem. Right now I have the situation, that a request blocks all following request.

The only way I could see that happening is if either:

 

- the requests are being sent on the same TCP connection (using HTTP keep-alives and maybe HTTP pipelining) and one of the requests is blocking the ones that arrive after it

 

- your requests are arriving on different TCP connections and are accessing some piece of shared data/functionality that is being blocked/deadlocked, thus blocking all requests that try to access it.

 

It is really hard to know what is going on without more details about your code and the requests.

Quote

So I want to cancel it as save as possible. In the main thread I know my TIdHTTPServer component and I know the TIdContext of the request I want to remove. What is the savest way to do it from "outside the request"?

The only option is to close the socket that belongs to that TIdContext.  But if your code is blocked/deadlocked on something that is not related to the socket itself, then closing the socket is likely to not have any/much effect in this situation.

 

You really need to narrow down WHAT exactly is blocking.  You still haven't answered my earlier questions about that.

Edited by Remy Lebeau

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×