Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Fix for mochiweb_acceptor crash under R15B02 #91

Merged
merged 1 commit into from

2 participants

@djnym
Collaborator

The source is still unclear but R15B02 now will return and emsgsize error
if the received packet is larger than the recvbuf. This can be tested with
the following (sorry I don't know how to integrate this sort of test into
mochiweb's tests).

-module(mochi_test).

-export([start/0,
         handle_http/1,
         test/1]).

start() ->
  application:start (inets),
  mochiweb_http:start([{port, 5678}, {loop, fun(Req) -> handle_http(Req) end}]).

handle_http(Req) ->
  Req:respond({ 200,
                [ {"Content-Type", "text/html"} ],
                [ "<html><body>Hello</body></html>" ]
              }).

test (Len) ->
  httpc:request (get, {"http://127.0.0.1:5678/",
                 [{"X-Random", [$a || _ <- lists:seq(1,Len)]}]}, [], []).

Once compiled you can run this with

erl -pa ebin -boot start_sasl

Then run with

mochi_test:start().
mochi_test:test(10000).

The result is different with R14B04 and R15B02. With R15B02 there was
a crash in the mochiweb_acceptor. This patch deals with that crash.

@djnym djnym Fix for mochiweb_acceptor crash under R15B02
The source is still unclear but R15B02 now will return and emsgsize error
if the received packet is larger than the recvbuf.  This can be tested with
the following (sorry I don't know how to integrate this sort of test into
mochiweb's tests).

-module(mochi_test).

-export([start/0,
         handle_http/1,
         test/1]).

start() ->
  application:start (inets),
  mochiweb_http:start([{port, 5678}, {loop, fun(Req) -> handle_http(Req) end}]).

handle_http(Req) ->
  Req:respond({ 200,
                [ {"Content-Type", "text/html"} ],
                [ "<html><body>Hello</body></html>" ]
              }).

test (Len) ->
  httpc:request (get, {"http://127.0.0.1:5678/",
                 [{"X-Random", [$a || _ <- lists:seq(1,Len)]}]}, [], []).

Once compiled you can run this with

erl -pa ebin -boot start_sasl

Then run with

mochi_test:start().
mochi_test:test(10000).

The result is different with R14B04 and R15B02.  With R15B02 there was
a crash in the mochiweb_acceptor.  This patch deals with that crash.
fedfd11
@etrepum etrepum merged commit dcd1076 into from
@nlebedenco nlebedenco referenced this pull request from a commit
@djnym djnym Make the acceptor crash optional.
So turns out the "Fix for mochiweb_acceptor crash under R15B02" from
#91 was a bug in OTP fixed in R16B.

erlang/otp@6aa9e71

So it worked in R14, was broken in R15 and got fixed in R16.  This commit
makes it such that things will work as well as possible in each version.

In rebar.config I set a compiler option if on R14 or R16, in mochiweb_http.erl
I make the extra R15 clause be added with the macro, then in
mochiweb_socket_server.erl I add in { exit_on_close, false } to the options.

In addition there is a script which will detect if the fix is needed based
on my test case from issue 91.

Just run 'make ; cd scripts ; ./check_for_gen_tcp_fix.erl' and it should
return true if the fix is in place.
4afdf42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 13, 2012
  1. @djnym

    Fix for mochiweb_acceptor crash under R15B02

    djnym authored
    The source is still unclear but R15B02 now will return and emsgsize error
    if the received packet is larger than the recvbuf.  This can be tested with
    the following (sorry I don't know how to integrate this sort of test into
    mochiweb's tests).
    
    -module(mochi_test).
    
    -export([start/0,
             handle_http/1,
             test/1]).
    
    start() ->
      application:start (inets),
      mochiweb_http:start([{port, 5678}, {loop, fun(Req) -> handle_http(Req) end}]).
    
    handle_http(Req) ->
      Req:respond({ 200,
                    [ {"Content-Type", "text/html"} ],
                    [ "<html><body>Hello</body></html>" ]
                  }).
    
    test (Len) ->
      httpc:request (get, {"http://127.0.0.1:5678/",
                     [{"X-Random", [$a || _ <- lists:seq(1,Len)]}]}, [], []).
    
    Once compiled you can run this with
    
    erl -pa ebin -boot start_sasl
    
    Then run with
    
    mochi_test:start().
    mochi_test:test(10000).
    
    The result is different with R14B04 and R15B02.  With R15B02 there was
    a crash in the mochiweb_acceptor.  This patch deals with that crash.
This page is out of date. Refresh to see the latest.
Showing with 8 additions and 0 deletions.
  1. +8 −0 src/mochiweb_http.erl
View
8 src/mochiweb_http.erl
@@ -66,6 +66,10 @@ request(Socket, Body) ->
{ssl_closed, _} ->
mochiweb_socket:close(Socket),
exit(normal);
+ {tcp_error,_,emsgsize} ->
+ % R15B02 returns this then closes the socket, so close and exit
+ mochiweb_socket:close(Socket),
+ exit(normal);
_Other ->
handle_invalid_request(Socket)
after ?REQUEST_RECV_TIMEOUT ->
@@ -95,6 +99,10 @@ headers(Socket, Request, Headers, Body, HeaderCount) ->
{tcp_closed, _} ->
mochiweb_socket:close(Socket),
exit(normal);
+ {tcp_error,_,emsgsize} ->
+ % R15B02 returns this then closes the socket, so close and exit
+ mochiweb_socket:close(Socket),
+ exit(normal);
_Other ->
handle_invalid_request(Socket, Request, Headers)
after ?HEADERS_RECV_TIMEOUT ->
Something went wrong with that request. Please try again.