Завершите процесс до истечения времени ожидания

#erlang #erlang-otp

#erlang #erlang-otp

Вопрос:

Кажется, что процесс erlang будет работать до истечения тайм-аута по умолчанию в 5 секунд, даже если он завершил свою работу.

У меня есть вызов gen_server, который выдает команду командной строке window CLI, которая может быть завершена менее чем за 1 секунду, но процесс ожидает 5 секунд, прежде чем я увижу результат операции. Что происходит? это как-то связано с временем ожидания, или это может быть что-то другое.

РЕДАКТИРОВАТЬ Этот вызов ничего не делает в течение 5 секунд (время ожидания по умолчанию!)

 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;
  

Комментарии:

1. Не могли бы вы опубликовать какой-нибудь пример кода, демонстрирующий проблему?

2. Убедитесь, что запущен sasl (application:start (sasl)), чтобы получать правильные отчеты об ошибках.

Ответ №1:

Я предполагаю, что os: cmd занимает столько времени, чтобы вернуть результаты. Возможно, у os: cmd возникают проблемы с определением того, когда команда rails завершена, и она не возвращается до тех пор, пока процесс не запустит время ожидания. Но из вашего кода я бы сказал, что наиболее вероятным виновником является вызов os: cmd.

Содержит ли возврат все, что вы ожидаете от него?

Комментарии:

1. Да, результат — это именно то, что я ожидал (список созданных файлов), и я согласен, что это должен быть вызов os: cmd, поскольку ванильный процесс возвращается почти мгновенно. Я думаю, вы ответили на мой вопрос, и я был довольно глуп. Я думаю, что именно это делает для вас изучение нового языка, когда вы не спите до 3 часов ночи. Но вы учитесь на своих ошибках, и я многому учусь благодаря ответам ваших парней, спасибо

2. нет проблем. Я совершил свою долю глупых ошибок, поверьте мне. Как вы сказали, это часть того, как мы учимся.

Ответ №2:

Вы по-прежнему не добавили никакой информации о том, в чем проблема. Но я вижу некоторые другие вещи, которые я хотел бы прокомментировать.

Текущий рабочий каталог

Вы используете file:set_cwd(Path) , поэтому запущенная команда унаследует этот путь. cwd файлового сервера является глобальным. Вероятно, вам вообще не следует использовать его в коде приложения. Это полезно для настройки cwd на то, куда вы хотите записывать аварийные дампы erlang и т.д.

Ваше желание разрешить rail выполняться с cwd в соответствии с Path лучше удовлетворить чем-то вроде этого:

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

То есть запустите оболочку для анализа командной строки, измените cwd оболочки и запустите Rails.

Блокировка gen_server

gen_server предназначен для сериализации обработки. То есть он обрабатывает одно сообщение за другим. Он не обрабатывает их все одновременно. Причина его существования заключается в том, чтобы не обрабатывать их одновременно.

Вы (в связи с другими затратами) выполняете некоторые очень дорогостоящие вычисления на gen_server: запускаете внешний процесс, который запускает это приложение rails. Собираетесь ли вы запускать не более одного приложения rails одновременно? (Я слышал о ruby on rails, требующем тонны памяти для каждого процесса, так что это может быть разумным решением).

Если вам не нужно обновлять состояние какими-либо значениями из дорогостоящего вызова, как в вашем примере кода, то вы можете использовать явный вызов gen_server:reply /2.

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

И тогда у вас есть

 rails_cmd(From, Path, Name, Args) ->
    Response = os:cmd(string:join(["cd", Path, "amp;amp;", "Rails", Name, Args], " ")),
    gen_server:reply(From, Response).
  

Комментарии:

1. Спасибо за ваш ответ, это очень помогло мне в процессе изучения erlang. Тем не менее, я попробовал ваше предложение использовать gen_server:reply / 2, и, похоже, это не дало мне ничего другого. Я не понимаю цели. Я очень рад, что это действие выполняется синхронно (я хочу дождаться его завершения, прежде чем делать что-либо еще), но, похоже, возврат занимает больше времени, чем фактическое действие Rails.

2. Мне кажется, что действие Rails выполняется, скажем, в течение 2 секунд, но я не вижу результатов до истечения времени ожидания gen_server через 5 секунд. Правильно ли я понимаю, что время ожидания по умолчанию составляет 5 секунд? Извините, если я веду себя глупо, но я начал изучать erlang всего 3 дня назад и ценю всю помощь, которую я могу получить.

3. Я не уверен, что ошибка erlang в том, что вы не видите результат быстрее. Тайм-ауты не должны приводить к тому, что возврат процесса erlang занимает больше времени. Я бы предположил, что ваша команда rails занимает больше времени или результат команды rails возвращается erlang дольше. Вы пробовали запускать ванильный процесс, который просто возвращает, ничего не делая? Держу пари, тогда у вас не будет замедления.

4. Черт! вы правы, это ошибка Rails, 5-секундная вещь сбила меня с толку