Search code examples
erlangyaws

Erlang/Yaws: Cannot start web server within application using .conf file


I'm kind of at a loss. YAWS works fine starting as a service during boot in LXQt 19.04. But I intended on using a rate limiter; setting it in arg_rewrite_mod. Having one VM run YAWS and another my application, setting code paths appropriately, I believe would yield subpar performance because the rate limiting calls would use OS-based IPC and not Erlang IPC. Hence there should be OS IPC overhead and not EVM overhead, correct?

I basically just wanted everything under one hood to eliminate that. This is one thing were there are probably a few ways to approach the problem (i.e. split up my project and duplicate pieces where needed) but I like the "simplicity" of everything in one place.

I'm getting an error, {badmatch, {error, enoent}}, in the shell after:

code:add_patha("/usr/lib/yaws/ebin").
application:start(yaws).

It is occurring on line 548 in yaws_server:setup_dirs/1 (Github)

setup_dirs(GC) ->
    Dir = yaws:id_dir(GC#gconf.id),
    Ctl = yaws:ctl_file(GC#gconf.id),
    ok = filelib:ensure_dir(Ctl),
    case file:list_dir(Dir) of
        {ok, LL} ->
            lists:foreach(
              fun(F) ->
                      file:delete(filename:join([Dir, F]))
              end, LL -- ["CTL"]); %%%  <---- LINE 548
        {error, RSN} ->
            error_logger:format("Failed to list ~p probably "
                                "due to permission errs: ~p",
                                [Dir, RSN]),
            erlang:error(RSN)
    end.

I made a UNIX group appname consisting of myself and the user yaws. I've gone around to various directories I found with sudo find / -group yaws -type d and set group permissions to the same as owner as well as reassigning the group from yaws to appname.... I believe since I did not set the id it is "default". My logs (/var/log/yaws/report.log) I was hoping would indicate the problem. They are empty.

I'm essentially using the default /etc/yaws/yaws.conf file. The server section has been removed and placed in /etc/yaws/conf.avail/ with a symlink in /etc/yaws/conf.d/.

UPDATE: The crash report ----

2020-03-27T08:30:04.131073-05:00 notice: Yaws: Using config file /etc/yaws/yaws.conf

2020-03-27T08:30:04.136142-05:00 error: use_old_ssl in yaws.conf is no longer supported - ignoring

2020-03-27T08:30:04.137441-05:00 notice: Yaws: Using global subconfig file /etc/yaws/conf.d/localhost.conf

2020-03-27T08:30:04.140979-05:00 error:
    crasher:
        initial call: yaws_server:init/1,
        pid: <0.114.0>,
        registered_name: [],
        error: {{badmatch,{error,enoent}},
            [{yaws_server,setup_dirs,1,[{file,"yaws_server.erl"},{line,548}]},
            {yaws_server,init2,5,[{file,"yaws_server.erl"},{line,224}]},
            {gen_server,init_it,2,[{file,"gen_server.erl"},{line,374}]},
            {gen_server,init_it,6,[{file,"gen_server.erl"},{line,342}]},
            {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,249}]}]},
        ancestors: [yaws_sup,<0.108.0>],
        message_queue_len: 0,
        messages: [],
        links: [<0.109.0>,#Port<0.6>],
        dictionary: [{gc,{gconf,"/usr/lib/yaws",false,612,"/var/log/yaws",
                ["/usr/local/lib/yaws-appmods/ebin","/usr/lib/yaws/examples/ebin"],
                [],[],30000,nolimit,400,1000000,8000,nolimit,[],10240,[],0,30,
                ["/usr/local/lib/yaws-appmods/include","/usr/lib/yaws/examples/include"],
                "/usr/bin/php-cgi","Yaws 2.0.6","default",false,[],8,undefined,
                [inet],yaws_session_server,undefined,120000,3600000,disable}},
        {start_time,{{2020,3,27},{8,30,4}}}],
        trap_exit: true,
        status: running,
        heap_size: 1598,
        stack_size: 27,
        reductions: 32410;
    neighbours:

2020-03-27T08:30:04.141195-05:00 error:
    supervisor: {local,yaws_sup},
    errorContext: start_error,
    reason: {{badmatch,{error,enoent}},
        [{yaws_server,setup_dirs,1,[{file,"yaws_server.erl"},{line,548}]},
        {yaws_server,init2,5,[{file,"yaws_server.erl"},{line,224}]},
        {gen_server,init_it,2,[{file,"gen_server.erl"},{line,374}]},    
        {gen_server,init_it,6,[{file,"gen_server.erl"},{line,342}]},
        {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,249}]}]},
    offender: [{pid,undefined},
        {id,yaws_server},
        {mfargs,
            {yaws_server,start_link,
                [{env,false,false,false,false,false,false,"default",latin1}]}},
        {restart_type,permanent},
        {shutdown,120000},
        {child_type,worker}]

2020-03-27T08:30:04.145621-05:00 error: 
    crasher:
        initial call: application_master:init/4,
        pid: <0.107.0>,
        registered_name: [],
        exit: {{{shutdown,{failed_to_start_child,yaws_server,{{badmatch,{error,enoent}},
            [{yaws_server,setup_dirs,1,[{file,"yaws_server.erl"},{line,548}]},
            {yaws_server,init2,5,[{file,"yaws_server.erl"},{line,224}]},
            {gen_server,init_it,2,[{file,"gen_server.erl"},{line,374}]},
            {gen_server,init_it,6,[{file,"gen_server.erl"},{line,342}]},
            {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,249}]}]}}},
        {yaws_app,start,[normal,[]]}},
            [{application_master,init,4,[{file,"application_master.erl"},{line,138}]},
            {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,249}]}]},
        ancestors: [<0.106.0>],
        message_queue_len: 1,
        messages: [{'EXIT',<0.108.0>,normal}],
        links: [<0.106.0>,<0.43.0>],
        dictionary: [],
        trap_exit: true,
        status: running,
        heap_size: 987,
        stack_size: 27,
        reductions: 225;
    neighbours:

2020-03-27T08:30:04.147171-05:00 notice:
    application: yaws,
    exited: {{shutdown,{failed_to_start_child,yaws_server,{{badmatch,{error,enoent}},
        [{yaws_server,setup_dirs,1,[{file,"yaws_server.erl"},{line,548}]},
        {yaws_server,init2,5,[{file,"yaws_server.erl"},{line,224}]},
        {gen_server,init_it,2,[{file,"gen_server.erl"},{line,374}]},
        {gen_server,init_it,6,[{file,"gen_server.erl"},{line,342}]},
        {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},
        {line,249}]}]}}},{yaws_app,start,[normal,[]]}},
    type: temporary

SOLUTION: From the help from the answer below and from having explored the various YAWS paths using find above I found the "default" home directory for me was `/var/cache/yaws/'. The following series of commands in the shell worked for me:

os:putenv("YAWSHOME","/var/cache/yaws/").
code:add_patha("/usr/lib/yaws/ebin").
application:start(yaws).

Solution

  • The source code line 548 shown in your question can't return {error, enoent}, but line 548 of yaws_server.erl for version 2.0.6 is

    ok = filelib:ensure_dir(Ctl),
    

    and this is what's returning the error tuple, which fails to match the expected atom ok and causes the failure.

    The function filelib:ensure_dir/1 verifies that the parent directories of its argument exist, attempting to create them if they don't. Solving this problem therefore requires determining the Ctl argument pathname in the code shown above.

    Since your server id is "default", Ctl in this case is defined as the path

    <HOME>/.yaws/yaws/default/CTL
    

    where <HOME> comes either from the setting for the YAWSHOME environment variable if it exists, otherwise from the setting for the HOME environment variable. Make sure one of these environment variables is set to a suitable path and that the .yaws/yaws/default subdirectory under it, if already present, has the appropriate permissions for your yaws user id and appname group id.