http:request hangs
Denis Titoruk
sidentdv@REDACTED
Thu Nov 19 15:24:40 CET 2009
Hi,
I am making asynchronous(keep-alive) http requests, sometimes requests
hang.
Version: R13B02-1
OS: Max OS X 10.5.8
Test case:
#!/usr/local/bin/escript
-define(URL, "http://my_local_web_server/").
executeMultipleTimes(0, _) -> ok;
executeMultipleTimes(N, F) -> F(N), executeMultipleTimes(N-1, F).
executeMultipleTimes(0, _, _) -> ok;
executeMultipleTimes(N, F, P) -> F(P, N), executeMultipleTimes(N-1, F,
P).
collectMessages(0, _) -> ok;
collectMessages(N, Msg) -> receive Msg -> collectMessages(N - 1, Msg)
end.
parallel(Parallel, Cycles, F) ->
Self = self(),
Pid = spawn_link(fun() ->
collectMessages(Parallel, finished),
Self ! ready
end),
executeMultipleTimes(Parallel, fun(P) ->
spawn_link(fun() ->
executeMultipleTimes(Cycles, F, P),
Pid ! finished
end)
end),
receive ready -> ok end.
main(_) ->
inets:start(),
F = fun(P, C) ->
io:format("starting ~p:~p~n",[P, C]),
URL = ?URL ++ "#" ++ integer_to_list(P) ++
":" ++ integer_to_list(C),
R = http:request(get, {URL, []}, [], []),
io:format("started ~p:~p~n",[P, C]),
case R of
{ok, _} -> ok;
_ -> io:format("error ~p:~p = [~p]~n",[P, C, R])
end
end,
parallel(4, 250, F).
--------------
Possible patch:
This patch appears to be working in my test case, but I am not sure it
solves the issue completely. Please take a look at yourselves.
httpc_handler.erl
287c287
< return_error(pipline_failed, Reason, State)
---
> {reply, {pipline_failed, Reason}, State}
340c340
< return_error(request_failed, Reason, State)
---
> {reply, {request_failed, Reason}, State}
343,350d342
< return_error(Error, Reason, State) ->
< Queue = case State#state.status of
< pipeline -> State#state.pipeline;
< keep_alive -> State#state.keep_alive;
< _ -> []
< end,
< {reply, {Error, Reason, [State#state.request |
queue:to_list(Queue)]}, State#state{ pipeline = queue:new(),
keep_alive = queue:new() }}.
<
httpc_manager.erl
366,370d365
< Requests = ets:match(State#state.handler_db, {'$1', Pid, '$2'}),
< [begin
< httpc_response:send(From, {Id, {error, internal_error}}) end ||
< [Id, From] <- Requests],
<
508,514c503
< Error -> %timeout pipelining failed
< case Error of
< {request_failed, _Reason, Queue} ->
< spawn(fun() -> restart_requests(Queue, State)
end);
< _E ->
< ok
< end,
---
> _ -> %timeout pipelining failed
518,532d506
< restart_requests([], _) -> ok;
< restart_requests([undefined | Queue], State) ->
< restart_requests(Queue, State);
< restart_requests([Request = #request{ from = answer_sent} | Queue],
State) ->
< restart_requests(Queue, State);
< restart_requests([Request | Queue], State) ->
< restart_request(Request, State),
< restart_requests(Queue, State).
<
< restart_request(Request, State) ->
< ProfileName = State#state.profile_name,
< catch ets:delete(State#state.handler_db, Request#request.id),
< httpc_manager:request(Request, ProfileName).
<
<
As you can see, there are two issues
1. when you receive {error, closed} in httpc_request:send & there are
few requests in queue
2. when handler process died
More information about the erlang-bugs
mailing list