Question

I am developing an SSL server application that is supposed to accept connections and respond in a simple fashion. I have created the skeleton of the application in a regular Erlang script which has been tested in the Erlang shell. This approach worked flawlessly, but when trying to implement it in Rebar the module stopped working.

My module looks like this (called api):

-define(SSL_OPTIONS, [{active, false}, {reuseaddr, true}, {certfile,"../priv/certificate.pem"}, {keyfile,"../priv/key.pem"}]).
start() ->
    try
        ssl:start(),
        Pid = listen(3000),
        {ok, Pid}
    catch
        _:_ -> error
    end.

listen(Port) ->
    {ok, LSocket} = ssl:listen(Port, ?SSL_OPTIONS),
    spawn(fun() -> accept(LSocket) end).

accept(LSocket) ->
    {ok, Socket} = ssl:transport_accept(LSocket),
    Pid = spawn(fun() -> communicator:loop(Socket) end),
    ssl:controlling_process(Socket, Pid),
    ?MODULE:accept(LSocket).

My implementation of the Rebar app looks like follows (called redirector_app):

-module(redirector_app).

-behaviour(application).

%% Application callbacks
-export([start/2, stop/1]).

%% ===================================================================
%% Application callbacks
%% ===================================================================

start(_StartType, _StartArgs) ->
    redirector_sup:start_link(),
    spawn(fun() -> init() end).

stop(_State) ->
    ok.

init() ->
    api:start(),
    ok.

I can start the api module by going into the ebin folder, where the .beam files are located and running the Erlang shell. Within the Erlang shell I run the command:

api:start().

However, when I try to run the Rebar app from the same folder and same shell with:

redirector_app:start([],[]).

I receive the following error:

Error in process <0.50.0> with exit value: {{badmatch,{error,einval}},[{ssl,transport_accept,2,[{file,"ssl.erl"},{line,197}]},{api,accept,1,[{file,"src/api.erl"},{line,25}]}]}

This doesn't change if I go to the root of the Rebar app and run the Erlang shell with:

$ erl -pa ebin/

I have narrowed the problem down to an issue with the connection. I think the connection actually closes before ssl:transport_accept(LSocket) is run.

Was it helpful?

Solution

Rebar app is the rebar itself. And what you do is called Erlang application. You can check documentation right here: http://www.erlang.org/doc/design_principles/applications.html

Erlang applications start differently. You must use application:start(redirector). It also means you must have redirector.app file in your ebin (or other search path) which must have {mod, {redirector_app,[]}}. You must ensure that all applications that you depend on are started before your application, this may be done automatically if you use Erlang releases http://www.erlang.org/doc/design_principles/release_structure.html

I recommend you to read an article http://www.metabrew.com/article/erlang-rebar-tutorial-generating-releases-upgrades

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top