Question

It seems that an erlang process will stay alive until the 5 sec default timeout even if it has finished it's work.

I have gen_server call that issues a command to the window CLI which can be completed in less than 1 sec but the process waits 5 sec before I see the result of the operation. What's going on? is it soemthing to do with the timeout, or might it be something else.

EDIT This call doesn't do anything for 5 seconds (the default timeout!)

handle_call({create_app, Path, Name, Args}, _From, State) ->
case filelib:ensure_dir(Path) of
    {error, Reason} ->
        {reply, Reason, State};
    _ ->
        file:set_cwd(Path),
        Response = os:cmd(string:join(["Rails", Name, Args], " ")),
        {reply, Response, State}
end;
Was it helpful?

Solution

I'm guessing the os:cmd is taking that long to return the results. It's possible that maybe the os:cmd is having trouble telling when the rails command is completed and doesn't return till the process triggers the timeout. But from your code I'd say the most likely culprit is the os:cmd call.

Does the return contain everything you expect it to?

OTHER TIPS

You still have not added any information on what the problem is. But I see some other things I'd like to comment on.

Current working dir

You are using file:set_cwd(Path) so the started command will inherit that path. The cwd of the file server is global. You should probably not be using it at all in application code. It's useful for setting the cwd to where you want erlang crash dumps to be written etc.

Your desire to let rail execute with the cwd according to Path is better served with something like this:

_ ->
    Response = os:cmd(string:join(["cd", Path, "&&", "Rails", Name, Args], " ")),
    {reply, Response, State}

That is, start a shell to parse the command line, have the shell change cwd and the start Rails.

Blocking a gen_server

The gen_server is there to serialize processing. That is, it processes one message after the other. It doesn't handle them all concurrently. It is its reason for existence to not handle them concurrently.

You are (in relation to other costs) doing some very costly computation in the gen_server: starting an external process that runs this rails application. Is it your intention to have at most one rails application running at any one time? (I've heard about ruby on rails requiring tons of memory per process, so it might be a sensible decision).

If you dont need to update the State with any values from a costly call, as in your example code, then you can use an explicit gen_server:reply/2 call.

_ ->
    spawn_link(fun () -> rails_cmd(From, Path, Name, Args) end),
    {no_reply, State}

And then you have

rails_cmd(From, Path, Name, Args) ->
    Response = os:cmd(string:join(["cd", Path, "&&", "Rails", Name, Args], " ")),
    gen_server:reply(From, Response).
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top