PageRenderTime 54ms CodeModel.GetById 42ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/src/mochiweb_acceptor.erl

http://github.com/basho/mochiweb
Erlang | 83 lines | 50 code | 10 blank | 23 comment | 0 complexity | 34854b5f17df5f08c71a03118685cbfc MD5 | raw file
 1%% @author Bob Ippolito <bob@mochimedia.com>
 2%% @copyright 2010 Mochi Media, Inc.
 3%%
 4%% Permission is hereby granted, free of charge, to any person obtaining a
 5%% copy of this software and associated documentation files (the "Software"),
 6%% to deal in the Software without restriction, including without limitation
 7%% the rights to use, copy, modify, merge, publish, distribute, sublicense,
 8%% and/or sell copies of the Software, and to permit persons to whom the
 9%% Software is furnished to do so, subject to the following conditions:
10%%
11%% The above copyright notice and this permission notice shall be included in
12%% all copies or substantial portions of the Software.
13%%
14%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17%% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19%% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20%% DEALINGS IN THE SOFTWARE.
21
22%% @doc MochiWeb acceptor.
23
24-module(mochiweb_acceptor).
25-author('bob@mochimedia.com').
26
27-include("internal.hrl").
28
29-export([start_link/3, start_link/4, init/4]).
30
31-define(EMFILE_SLEEP_MSEC, 100).
32
33start_link(Server, Listen, Loop) ->
34    start_link(Server, Listen, Loop, []).
35
36start_link(Server, Listen, Loop, Opts) ->
37    proc_lib:spawn_link(?MODULE, init, [Server, Listen, Loop, Opts]).
38
39do_accept(Server, Listen) ->
40    T1 = os:timestamp(),
41    case mochiweb_socket:transport_accept(Listen) of
42        {ok, Socket} ->
43            gen_server:cast(Server, {accepted, self(), timer:now_diff(os:timestamp(), T1)}),
44            mochiweb_socket:finish_accept(Socket);
45        Other ->
46            Other
47    end.
48
49init(Server, Listen, Loop, Opts) ->
50    case catch do_accept(Server, Listen) of
51        {ok, Socket} ->
52            call_loop(Loop, Socket, Opts);
53        {error, Err} when Err =:= closed orelse
54                          Err =:= esslaccept orelse
55                          Err =:= timeout ->
56            exit(normal);
57        Other ->
58            %% Mitigate out of file descriptor scenario by sleeping for a
59            %% short time to slow error rate
60            case Other of
61                {error, emfile} ->
62                    receive
63                    after ?EMFILE_SLEEP_MSEC ->
64                            ok
65                    end;
66                _ ->
67                    ok
68            end,
69            error_logger:error_report(
70              [{application, mochiweb},
71               "Accept failed error",
72               lists:flatten(io_lib:format("~p", [Other]))]),
73            exit({error, accept_failed})
74    end.
75
76call_loop({M, F}, Socket, Opts) ->
77    M:F(Socket, Opts);
78call_loop({M, F, [A1]}, Socket, Opts) ->
79    M:F(Socket, Opts, A1);
80call_loop({M, F, A}, Socket, Opts) ->
81    erlang:apply(M, F, [Socket, Opts | A]);
82call_loop(Loop, Socket, Opts) ->
83    Loop(Socket, Opts).