Frequent crashes in inets http client (R12B-5)

Chris Newcombe chris.newcombe@REDACTED
Fri Jun 5 16:43:54 CEST 2009


Is there a patch for the following issue?



It was reported a while ago:
http://groups.google.com/group/erlang-programming/browse_thread/thread/4c497978c75ed6a9/18d9a242df81ba3a?lnk=gst&q=badrecord#18d9a242df81ba3a(but
I didn't see any replies)



Here's a bit more detail:



httpc_handler is crashing with



       {badrecord,request}



(BTW it would be great if badrecord errors also contained the incorrect
term, not just the name of the expected record type)



It’s crashing in



       httpc_handler,handle_info,2



The last message received by the gen_server is



      {timeout,#Ref<0.0.0.9038>}



The gen_server #state is




{state,undefined,{tcp_session,{{"my-test-url",8080},<0.709.0>},false,http,#Port<0.1351>,1},undefined,undefined,undefined,undefined,{[],[]},pipeline,[#Ref<0.0.0.5834>],nolimit,nolimit,{options,{undefined,[]},20000,1,100,disabled,enabled,false},{timers,[],#Ref<0.0.0.19293>}



I think the relevant element is the first one (request).

i.e. request == undefined



Given the message, it seems almost certain that the crash is in the second
timeout clause of handle_info,

(marked below with ***).

This clause will fire even if request == undefined, but will try to use
Request#request.from, which crashes with {badrecord,request}



       %%% Timeouts

       %% Internaly, to a request handling process, a request time out is

       %% seen as a canceld request.

       handle_info({timeout, RequestId}, State =

                   #state{request = Request = #request{id = RequestId}}) ->

           httpc_response:send(Request#request.from,

                         httpc_response:error(Request,timeout)),

           {stop, normal,

            State#state{canceled = [RequestId | State#state.canceled],

                        request = Request#request{from = answer_sent}}};



***    handle_info({timeout, RequestId}, State = #state{request = Request})
->

           httpc_response:send(Request#request.from,

                              httpc_response:error(Request,timeout)),

           {noreply, State#state{canceled = [RequestId |
State#state.canceled]}};



       handle_info(timeout_pipeline, State = #state{request = undefined}) ->

           {stop, normal, State};



It looks like State#state.request is being set to undefined without
cancelling an in-progress request timer.


I've only glanced at the code, but both of the following clauses appear to
do that.

(But it could easily be something else.)



        %% On a redirect or retry the current request becomes

        %% obsolete and the manager will create a new request

        %% with the same id as the current.

        {redirect, NewRequest, Data}->

            ok = httpc_manager:redirect_request(NewRequest, ProfileName),

            handle_pipeline(State#state{request = undefined}, Data);

        {retry, TimeNewRequest, Data}->

            ok = httpc_manager:retry_request(TimeNewRequest, ProfileName),

            handle_pipeline(State#state{request = undefined}, Data);



thanks,



Chris


More information about the erlang-questions mailing list