使进程在超时之前结束

发布于 2024-08-04 02:58:33 字数 536 浏览 3 评论 0原文

似乎 erlang 进程将保持活动状态,直到 5 秒默认超时,即使它已经完成了工作。

我有 gen_server 调用,它向窗口 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;

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

赠我空喜 2024-08-11 02:58:33

我猜 os:cmd 需要很长时间才能返回结果。 os:cmd 可能无法判断 Rails 命令何时完成,并且在进程触发超时之前不会返回。但从你的代码来看,我想说最有可能的罪魁祸首是 os:cmd 调用。

退货是否包含您期望的所有内容?

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?

一向肩并 2024-08-11 02:58:33

您还没有添加任何有关问题所在的信息。但我还想对其他一些事情发表评论。

当前工作目录

您正在使用file:set_cwd(Path),因此启动的命令将继承该路径。文件服务器的cwd是全局的。您可能根本不应该在应用程序代码中使用它。它对于将 cwd 设置为您希望写入 erlang 故障转储的位置很有用。

您希望让 Rail 根据 Path 使用 cwd 执行的愿望可以通过以下方式更好地满足:

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

也就是说,启动一个shell 解析命令行,让 shell 更改 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, "&&", "Rails", Name, Args], " ")),
    gen_server:reply(From, Response).

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).
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文