<html><head></head><body bgcolor="#FFFFFF"><div>Thanks, Fred</div><div><br></div><div>That describe everything. Wish I suggested tail recursion yesterday.</div><div><br></div><div>-- Aleksandr<br><br><br></div><div><br>18.07.2012, в 6:34, Fred Hebert <<a href="mailto:mononcqc@ferd.ca">mononcqc@ferd.ca</a>> написал(а):<br><br></div><div></div><blockquote type="cite"><div>
  
    <meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
  
  
    First of all, you have to understand that when a request comes in
    cowboy, there goes a chain of command based on how you described
    your listener in a call to <tt>cowboy:start_listener</tt>. That
    chain does things like accepting requests, handling socket/port
    ownership, and dispatching stuff.<br>
    <br>
    One of the steps in there is to start a process based on the
    protocol you picked. In this case, the protocol is handled by <tt>cowboy_http_protocol</tt>,
    and the function is <tt>request</tt>.<br>
    <br>
    That's where your stack trace begins.<br>
    <br>
    When a call is made in Erlang, and that call is the last thing to
    happen in a function's body (it's a tail call), the stack trace for
    the current one will be dropped. This is to say, if I have:<br>
    <br>
    <tt>a() -> b(), ok.<br>
      b() -> hello, c().<br>
      c() -> ok.</tt><br>
    <br>
    and I'm in <tt>b()</tt>, the stack trace will be <tt>[a, b]</tt>.
    <tt>a()</tt> is there because <tt>b()</tt> isn't happening in last
    place. We thus need to store that we're part of <tt>'a'</tt> in
    order to return to it in the future and execute the '<tt>ok</tt>'
    expression. Then <tt>b()</tt> calls <tt>c()</tt>.<br>
    <br>
    Because <tt>b()</tt> ends with a call to <tt>c()</tt>, and we know
    that <tt>b()</tt> returns to <tt>a()</tt>, we can replace <tt>b</tt>
    in <tt>[a,b]</tt> and change it to <tt>[a,c]</tt>. This is good,
    because when we do things like recursing forever in a server loop,
    it keeps us from growing the stack until it crashes (stack overflow,
    or OOM). We drop whatever stack trace information we can afford to
    drop.<br>
    <br>
    So when your error happens, it's on line 172.<br>
    <br>
    This goes through:<br>
    <br>
    <tt>request</tt> -> <tt>parse_header</tt> -> <tt>wait_header</tt><br>
    <br>
    <tt>parse_header</tt> and <tt>wait_header</tt> both happen in a
    tail position. This explains why your stack trace shows <b>nothing</b>
    but request. They're each removed from the stack trace before. That
    explains why you get:<br>
    <br>
    <div><tt>[{cowboy_http_protocol,request,2,</tt></div>
    <div><tt>                     
         [{file,"src/cowboy_http_protocol.erl"},{line,172}]}]</tt></div>
    <br>
    Consider yourself lucky we now have line numbers to help!<br>
    <br>
    Now for the shell, when you get an error there, it looks like:<br>
    <br>
    <div><tt>[{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,576}]},</tt></div>
    <div><tt> {erl_eval,try_clauses,8,[{file,"erl_eval.erl"},{line,767}]},</tt></div>
    <div><tt> {shell,exprs,7,[{file,"shell.erl"},{line,668}]},</tt></div>
    <div><tt> {shell,eval_exprs,7,[{file,"shell.erl"},{line,623}]},</tt></div>
    <div><tt> {shell,eval_loop,3,[{file,"shell.erl"},{line,608}]}]</tt><br>
      <br>
      This is simply because shell evaluation and whatnot, for all these
      functions, is <b>not</b> making these calls in a tail position.
      This is part of how the shell works, and explains why you'll get a
      longer stack trace there than with compiled code.<br>
      <br>
      You can see part of the variation there:<br>
      <tt><br>
        1> spawn(fun() -> try<br>
        1>         erlang:error(xxxxxREQ_error)<br>
        1>     catch<br>
        1>         error:_ -><br>
        1>             io:format("~nxxxxxREQ_error stacktrace~n~p~n",
        [erlang:get_stacktrace()])<br>
        1>     end  <br>
        1> end).<br>
        <br>
        xxxxxREQ_error stacktrace<br>
        [{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,576}]},<br>
         {erl_eval,try_clauses,8,[{file,"erl_eval.erl"},{line,767}]}]<br>
        <0.71.0></tt><br>
    </div>
    <br>
    You'll see that for that one, part of the evaluation was done
    beforehand. When the new function is spawned and starts running, the
    'shell' module is no longer involved, and the stack trace changes.
    New processes do not carry old stack information as they need not to
    return anywhere.<br>
    <br>
    So it's not surprising that you get barely nothing from cowboy when
    the function you get is pretty much the only one that can be allowed
    in the stack trace by these rules. It's brand new and the error
    happens after a chain of tail calls.<br>
    <br>
    I hope this helps.<br>
    <br>
    <div class="moz-cite-prefix">On 12-07-17 2:09 PM, Aleksandr
      Vinokurov wrote:<br>
    </div>
    <blockquote cite="mid:CANLxesLmZTF5bqoSLj7SUSVM2auEOb-kfJRpby_GXp1+6m5=ZQ@mail.gmail.com" type="cite">
      <div><br>
      </div>
      <div><br>
      </div>
      Hello all,
      <div><br>
      </div>
      <div>I need to see a backtrace of a cowboy_http_protocol:request/2
        and to get it I've added some code in the function (marked
        strong):<br clear="all">
        <div style="text-align:left">
          <br>
        </div>
        <div>
          <div>request(_Any, State) -></div>
          <div>%%%%%%%%%</div>
          <div>   <b> io:format("~n~p~n", [{xxxxx161, State, _Any}]),</b></div>
          <div><b>    try</b></div>
          <div><b>        erlang:error(xxxxx161_error)</b></div>
          <div><b>    catch</b></div>
          <div><b>        error:X -></b></div>
          <div><b>            io:format("~nxxxxx161_error
              stacktrace~n~p~n", [erlang:get_stacktrace()]),</b></div>
          <div><b>            erlang:error(X)</b></div>
          <div><b>    end,</b></div>
          <div><b>%%%%%%%%%%%</b></div>
          <div><span class="Apple-tab-span" style="white-space:pre"> </span>error_terminate(400,
            State).</div>
        </div>
        <div><br>
        </div>
        <div><br>
        </div>
        <div>After recompilation and reloading I see only one line in
          backtrace list:</div>
        <div>
          <div><br>
          </div>
          <div>(web@AVINOKUROV)1> </div>
          <div>{xxxxx161,</div>
          <div>   
            {state,<0.85.0>,#Port<0.3809>,cowboy_tcp_transport,</div>
          <div>        [{'_',</div>
          <div>             [{[<<"token">>],</div>
          <div>               ps_oauth_2_api_external_token_endpoint,</div>
          <div>               [{config,off,off,</div>
          <div>                    {{127,0,0,1},8080},</div>
          <div>                    {{127,0,0,1},8180},</div>
          <div>                    {{127,0,0,1},8443},</div>
          <div>                    {{127,0,0,1},8543},</div>
          <div>                    [{"jay","123"},"bob",{"matt","321"}],</div>
          <div>                    "<a moz-do-not-send="true" href="http://127.0.0.1:8881/client-storage">http://127.0.0.1:8881/client-storage</a>",</div>
          <div>                   
            [{<<"apt1">>,{seconds,600,"600"}},</div>
          <div>                   
             {<<"apt2">>,{seconds,6000,"6000"}}],</div>
          <div>                    {seconds,3600,"3600"},</div>
          <div>                    {seconds,600,"600"},</div>
          <div>                    undefined,</div>
          <div>                    {bytes,64},</div>
          <div>                    {bytes,256},</div>
          <div>                    {bytes,1024}},</div>
          <div>               
            {external_api_applications,ps_oauth_2_ext_api_applications}]},</div>
          <div>             
            {'_',ps_oauth_2_index,[external,#Fun<ps_oauth_2.2.99090327>]}]}],</div>
          <div>        {ps_oauth_2_api_external_token_endpoint,</div>
          <div>            [{config,off,off,</div>
          <div>                 {{127,0,0,1},8080},</div>
          <div>                 {{127,0,0,1},8180},</div>
          <div>                 {{127,0,0,1},8443},</div>
          <div>                 {{127,0,0,1},8543},</div>
          <div>                 [{"jay","123"},"bob",{"matt","321"}],</div>
          <div>                 "<a moz-do-not-send="true" href="http://127.0.0.1:8881/client-storage">http://127.0.0.1:8881/client-storage</a>",</div>
          <div>               
             [{<<"apt1">>,{seconds,600,"600"}},</div>
          <div>                 
            {<<"apt2">>,{seconds,6000,"6000"}}],</div>
          <div>                 {seconds,3600,"3600"},</div>
          <div>                 {seconds,600,"600"},</div>
          <div>                 undefined,</div>
          <div>                 {bytes,64},</div>
          <div>                 {bytes,256},</div>
          <div>                 {bytes,1024}},</div>
          <div>
                       
             {external_api_applications,ps_oauth_2_ext_api_applications}]},</div>
          <div>        undefined,undefined,</div>
          <div>        {#Fun<cowboy_http.urldecode.2>,crash},</div>
          <div>        0,5,213,infinity,4096,5000,</div>
          <div>        <<"authorization: Basic
            YXBwMToxMjM=\r\nconnection:
keep-alive\r\n\r\ngrant_type=authorization_code&code=1pD8tsKZTFXw3sbbOPbLtCU0oSg5CWx%2FohR8AC%2BAuTROzsx1DQC6LLm4h6iaOvupV5cOs3cAqBqsWB%2BtzfxVtg%3D%3D">>,</div>
          <div>        false,infinity,undefined},</div>
          <div>    {http_error,<<"<a moz-do-not-send="true" href="http://7.0.0.1:8080">7.0.0.1:8080</a>\r\n">>}}</div>
        </div>
        <div><br>
        </div>
        <div>
          <div>(web@AVINOKUROV)1> </div>
          <div>xxxxx161_error stacktrace</div>
          <div>[{cowboy_http_protocol,request,2,</div>
          <div>                     
             [{file,"src/cowboy_http_protocol.erl"},{line,172}]}]</div>
          <div>(web@AVINOKUROV)1></div>
        </div>
        <div>
          <div><br>
          </div>
          <div>=ERROR REPORT==== 17-Jul-2012::21:51:26 ===</div>
          <div>Error in process <0.1373.0> on node
            'web@AVINOKUROV' with exit value:
{xxxxx161_error,[{cowboy_http_protocol,request,2,[{file,"src/cowboy_http_protocol.erl"},{line,176}]}]}</div>
        </div>
        <div><br>
        </div>
        <div>
          <div>=SUPERVISOR REPORT==== 17-Jul-2012::21:51:26 ===</div>
          <div>     Supervisor: {<0.86.0>,cowboy_requests_sup}</div>
          <div>     Context:    child_terminated</div>
          <div>     Reason:     {xxxxx161_error,</div>
          <div>                     [{cowboy_http_protocol,request,2,</div>
          <div>                         
            [{file,"src/cowboy_http_protocol.erl"},</div>
          <div>                           {line,176}]}]}</div>
          <div>     Offender:   [{pid,<0.1373.0>},</div>
          <div>                  {name,cowboy_requests_sup},</div>
          <div>                 
            {mfargs,{cowboy_requests_sup,start_request,undefined}},</div>
          <div>                  {restart_type,temporary},</div>
          <div>                  {shutdown,brutal_kill},</div>
          <div>                  {child_type,worker}]</div>
        </div>
        <div><br>
        </div>
        <div>If I call that code in shell I see a full backtrace like
          that:</div>
        <div><br>
        </div>
        <div>
          <div>(web@AVINOKUROV)4> try</div>
          <div>        erlang:error(xxxxxREQ_error)</div>
          <div>    catch</div>
          <div>        error:_ -></div>
          <div>            io:format("~nxxxxxREQ_error
            stacktrace~n~p~n", [erlang:get_stacktrace()])</div>
          <div>    end.</div>
          <div><br>
          </div>
          <div>xxxxxREQ_error stacktrace</div>
          <div>[{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,576}]},</div>
          <div> {erl_eval,try_clauses,8,[{file,"erl_eval.erl"},{line,767}]},</div>
          <div> {shell,exprs,7,[{file,"shell.erl"},{line,668}]},</div>
          <div> {shell,eval_exprs,7,[{file,"shell.erl"},{line,623}]},</div>
          <div> {shell,eval_loop,3,[{file,"shell.erl"},{line,608}]}]</div>
          <div>ok</div>
          <div>(web@AVINOKUROV)5> </div>
        </div>
        <div><br>
        </div>
        <div>
          I don't understand what am I doing wrong.</div>
        <div><br>
        </div>
        -- <br>
        <div>Александр Винокуров</div>
        <div>+7 (921) 982-21-43</div>
        <div>@aleksandrvin</div>
        <br>
      </div>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <br>
      <pre wrap="">_______________________________________________
erlang-questions mailing list
<a class="moz-txt-link-abbreviated" href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a>
<a class="moz-txt-link-freetext" href="http://erlang.org/mailman/listinfo/erlang-questions">http://erlang.org/mailman/listinfo/erlang-questions</a>
</pre>
    </blockquote>
    <br>
  

</div></blockquote></body></html>