PDA

View Full Version : http timeout not used?



Joe Bob
2006-11-28, 21:51
Hey all,

I occasionally experience some wierd behavior from the new xmradio plugin which uses an SS friendly wrapper for synchronously invoking http requests. The problem I'm having is that if there is a problem with the connection, my client hangs (as it is perpetually waiting for the async request to complete). After looking at the SimpleAsyncHTTP code, I noticed that it looks up a value for a timeout, but never sets the value on the request. I'm not very familiar with this code and was wondering if this is as designed or a bug.

Thanks in advance,
JB

andyg
2006-11-28, 22:05
On Nov 28, 2006, at 11:51 PM, Joe Bob wrote:

>
> Hey all,
>
> I occasionally experience some wierd behavior from the new xmradio
> plugin which uses an SS friendly wrapper for synchronously invoking
> http requests. The problem I'm having is that if there is a problem
> with the connection, my client hangs (as it is perpetually waiting for
> the async request to complete). After looking at the SimpleAsyncHTTP
> code, I noticed that it looks up a value for a timeout, but never sets
> the value on the request. I'm not very familiar with this code and
> was
> wondering if this is as designed or a bug.

I'm not familiar with the plugin but I hope you don't really mean it
makes synchronous HTTP requests. :)

There was a timeout bug I fixed recently, but it was related to the
timeout always being 10 seconds instead of the proper value set by
the user. What you describe sounds like something else, though.
Can you point out the part of SimpleAsyncHTTP that you're referring to?

Joe Bob
2006-11-28, 22:32
Hey Andy,

Thanks for your prompt reply.

It does not make synchronous requests, but it does block until the request completes (in the meantime it spins the idle loop, ::idle()).

Look on or around line 124 in SimpleAsyncHTTP:


my $timeout
= $self->{params}->{Timeout}
|| Slim::Utils::Prefs::get('remotestreamtimeout')
|| 10;


This variable is never used.

I was able to troll through Slim::Networking::HTTP and find that a timeout was being used in _http_read() and _http_read_body(), but my assumption was that this timeout will only be effective after the connection is opened.

Thanks again for the reply,
JB

Triode
2006-11-29, 11:29
> It does not make synchronous requests, but it does block until the
> request completes (in the meantime it spins the idle loop, ::idle()).

Hopefully you mean ::idleStreams? This will maintain streaming, display animation and keep the client slimproto connections alive,
but otherwise block server UI. However it avoids any problems which come serving http inside itself [not sure if this is relavent
to you].

Joe Bob
2006-11-29, 20:56
Hey Triode,

I am using ::idle(). Is ::idleStreams() more appropriate? I thought ::idle() would be less restrictive (friendlier) and, so far, ::idle() seems to be working just fine.

I would be interested in knowing why one is better than the other.

Thanks for the information.

Joe Bob
2006-11-29, 21:01
Hey Andy,

I think this was a red herring. After tracing through the code, it looks like a timeout does get set somewhere (even if it doesn't come from the invocant).

My guess is I'm probably not handling an error condition appropriately and am leaving the client blocked. This is only a guess at this point since the problem is difficult to reproduce and I never have logging turned on when it occurs.

Thanks again for the help.

Triode
2006-11-30, 13:33
> I am using ::idle(). Is ::idleStreams() more appropriate? I thought
> ::idle() would be less restrictive (friendlier) and, so far, ::idle()
> seems to be working just fine.

Well idleStreams was intended for this purpose as it only does a subset of idle. Specifically it only calls select for streaming
and slimproto sockets. It does not process any IR or other functions. This means it is safer than idle, but will give the
impression of blocking the user interface.

The actual issues came from calling select within a task which was a select callback as it was possible to process web requests in
the wrong order in pathalogical cases. I think you are actually safe calling idle(), but bear in mind that this was not the
intention of the function and nothing else in the server does it. If you see problems switch to idleStreams and see if they go
away. The preferred option is to use async http so that select callbacks always return rapidly.

Adrian

Joe Bob
2006-11-30, 17:51
Hey Adrian,

Thanks for the information. I actually am using the async http requests, but cannot handle the response in an asynchronous fashion, which is why I implemented a SS friendly "SimpleSyncHTTP" module in the first place.

Detailed explanation follows:
I needed this to implement a specialized protocol handler for xm stations. A specialized protocol handler was required because the play URLs are transient. When SS invokes my protocol handler, I need to request a play URL and return this back to the server through canDirectStream(). This is the reason I need to block. Since this wrapper worked so well, I decided to apply it to other portions of the code. This greatly simplified the api wrapper for xm's online service and made the code paths more predictable. Initially I was looking at spawning separate threads, etc. but am new to perl (only been at it for a couple of months; almost as long as I've had my SB :-)) and could not figure out the threading model used by the server. The best I could come up with was spinning the idle() loop, similar to what you would do in a windows app when you wanted to performing some long running task, but wanted the ui to remain responsive.

Probably more than you wanted to know.

Thanks again for the information.
Rob

andyg
2006-11-30, 18:30
On Nov 30, 2006, at 7:51 PM, Joe Bob wrote:

>
> Hey Adrian,
>
> Thanks for the information. I actually am using the async http
> requests, but cannot handle the response in an asynchronous fashion,
> which is why I implemented a SS friendly "SimpleSyncHTTP" module in
> the
> first place.
>
> Detailed explanation follows:
> I needed this to implement a specialized protocol handler for xm
> stations. A specialized protocol handler was required because the
> play
> URLs are transient. When SS invokes my protocol handler, I need to
> request a play URL and return this back to the server through
> canDirectStream(). This is the reason I need to block. Since this
> wrapper worked so well, I decided to apply it to other portions of the
> code. This greatly simplified the api wrapper for xm's online service
> and made the code paths more predictable. Initially I was looking at
> spawning separate threads, etc. but am new to perl (only been at it
> for
> a couple of months; almost as long as I've had my SB :-)) and could
> not
> figure out the threading model used by the server. The best I could
> come up with was spinning the idle() loop, similar to what you
> would do
> in a windows app when you wanted to performing some long running task,
> but wanted the ui to remain responsive.

FYI, I've just recently needed to async this part of the server, so
you can now make async requests in a protocol handler after a
playlist play command. Coming soon to 7.0... :)