<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>