<div dir="ltr"><div>In <a href="http://erlang.org/pipermail/erlang-questions/2014-February/077788.html">http://erlang.org/pipermail/erlang-questions/2014-February/077788.html</a></div><div>and elsewhere, users observed that httpc would occasionally encounter</div><div>`{error,socket_closed_remotely}` when querying a web service of some sort.</div><div>The workaround was to use http 1.0, as opposed to 1.1, which is somewhat</div><div>of an unsatisfying resolution.</div><div><br></div><div>I have encountered this same problem and have tried to create a minimal</div><div>example that reproduces the issue using a public url to post a simple JSON</div><div>body. I am hoping that the following provides enough information to </div><div>constitute a useful bug report.</div><div><br></div><div>The following code will quickly cause the problem to appear; however,</div><div>the problem *disappears* when  {"connection", "close"} is added to</div><div>the header. In fact I cannot reproduce the problem ever when this</div><div>header is used.</div><div><br></div><div>My code is as follows:</div><div><br></div><div>-module(httpc_bug).</div><div>-export([test/0]).</div><div><br></div><div>test()-></div><div>    httpc:set_options([{max_keep_alive_length, 0},</div><div>                                 {max_pipeline_length, 0},</div><div>                                 {max_sessions, 0}]),</div><div>    test_put(0).</div><div><br></div><div>test_put(N) -></div><div>    Url = "<a href="https://posttestserver.com/post.php">https://posttestserver.com/post.php</a>",</div><div>    ContentType= "application/json",</div><div>    Body = <<"{\"type\":\"body type\",\"value\":2}">>,</div><div>    Header = [],</div><div>    HttpOptions = [],</div><div>    Options = [],</div><div><br></div><div>    case httpc:request(post, {Url, Header, ContentType, Body},</div><div>                                  HttpOptions,</div><div>                                  Options) of</div><div>        {ok, {{_V, _Cd, _R}, _RespHeader, B }} -></div><div>                io:format("~p[~p]:~p~n”, [self(), N, B]),</div><div>                test_put(N+1);</div><div>        {error, Reason} -></div><div>                io:format("~p: died after ~p iterations with: ~p. ~n.",</div><div>                               [self(), N, Reason])</div><div>        end.</div><div><br></div><div><br></div><div>A typical run looks like this:</div><div><br></div><div>Erlang/OTP 17 [erts-6.2] [source-aaaefb3] [64-bit] [smp:8:8]</div><div>[async-threads:10] [hipe] [kernel-poll:false]</div><div><br></div><div><br></div><div>Eshell V6.2  (abort with ^G)</div><div>1> inets:start().</div><div>ok</div><div>2> ssl:start().</div><div>ok</div><div>3> code:load_file(httpc_bug).</div><div>{module,httpc_bug}</div><div>4> httpc_bug:test(1).</div><div>[<0.15201.0>]</div><div><0.15201.0>[0]:"Successfully dumped 0 post variables.\nView it at</div><div><a href="http://www.posttestserver.com/data/2015/03/13/19.21.45157935823\nPost">http://www.posttestserver.com/data/2015/03/13/19.21.45157935823\nPost</a> body</div><div>was 30 chars long."</div><div><0.15201.0>[1]:"Successfully dumped 0 post variables.\nView it at</div><div><a href="http://www.posttestserver.com/data/2015/03/13/19.21.451784952425\nPost">http://www.posttestserver.com/data/2015/03/13/19.21.451784952425\nPost</a> body</div><div>was 30 chars long."</div><div>.</div><div>. SNIP</div><div>.</div><div><0.15201.0>: died after 102 iterations with: socket_closed_remotely.</div><div><br></div><div><br></div><div>I just did five runs, four died in under 410 iterations, and the fifth took</div><div>809 iterations.</div><div><br></div><div><br></div><div>Again, adding {"connection", "close"} to the header causes the problem to</div><div>disappear.</div><div><br></div><div>By examining the contents of the http_manager__session_db before each call</div><div>to the httpc:request, I am pretty sure that the flow goes:</div><div><br></div><div><br></div><div>httpc_manager.erl line 759 — within a handle_request clause</div><div><br></div><div>handle_request(Request, State = #state{options = Options}) -></div><div>    NewRequest = handle_cookies(generate_request_id(Request), State),</div><div>    SessionType = session_type(Options),</div><div>    case select_session(Request#request.method,</div><div>                        Request#request.address,</div><div>                        Request#request.scheme, SessionType, State) of</div><div>    {ok, HandlerPid} -></div><div>        -> pipeline_or_keep_alive(NewRequest, HandlerPid, State); <-</div><div>        .</div><div>        . SNIP</div><div>        .</div><div><br></div><div>To</div><div><br></div><div>httpc_handler.erl line 323 — within a handle_call where keep_alive requests</div><div>are handled.</div><div><br></div><div>Hope this is useful.</div><div><br></div><div>Thanks</div><div><br></div></div>