<div dir="ltr">I recently ran into a very scary issue that appears to be related to httpc.<div><br></div><div>I was hitting a web API millions of times, with varying URLs; e.g., /users/9000000, /users/9000001, etc., at a rate of around 100-400 requests/sec, using httpc:request, each request spawned by a different worker:</div>

<div><br></div><div><div>get_user(UserID) -></div><div>  get_user_r(UserID, 10).</div><div>get_user_r(UserID, 0) -></div><div>  io:format("dying because ran out of retries on ~p~n",[UserID]);</div><div>get_user_r(UserID, Retries) -></div>

<div>  Url = lists:concat(["<a href="http://example.com/users/">http://example.com/users/</a>", UserID]),</div><div>  Filename = lists:concat(["users/-", UserID, ".json"]),</div><div>  io:format("requesting user: ~p~n", [UserID]),</div>

<div>  case httpc:request(Url) of</div><div>    {ok, Result} -></div><div>      {_, _, Body} = Result,</div><div>      file:write_file(Filename, Body),</div><div>      userscrapemaster ! {ok, ClanID};</div><div>    {error, Reason} -></div>

<div>      io:format("error for user ~p: ~p~n",[UserID, Reason]),</div><div>      get_members_r(UserID, Retries - 1)</div></div><div><br></div><div>A small (< 0.1%) but significant percentage of the time, the httpc:request call for completely different workers MIXED UP THEIR RESPONSES with other concurrent requests.</div>

<div><br></div><div>For example, sometimes /users/5000 returned success but provided the body that /users/5001 should have returned, and /users/5001 returned the body that /users/5002 should have returned, and /users/5002 returned the body that /users/5000 should have returned.  Or, /users/5009 returned the response for /users/5010, and vice versa.</div>

<div><br></div><div>There appeared to be no obvious pattern except that all those calls were concurrent, and pragmatically I didn't have the time to go chasing into httpc to try to figure out where the state was getting scrambled, but as a test I moved the call over to lhttpc without changing the structure of the code otherwise, and the mixed responses went away.</div>

<div><br></div><div>If I get some time I'll try to dig into httpc to understand what happened there, but as a warning to others: httpc looks like it has a hidden race condition or other bug, and lhttpc does not.</div>

<div><br></div><div>F.</div></div>