【问题标题】:How to correctly start a process from a specific directory with Lwt如何使用 Lwt 从特定目录正确启动进程
【发布时间】:2015-06-16 08:48:17
【问题描述】:

使用函数Sys.getpwdLwt_unix.chdirLwt_process.exec可以很容易地通过Lwt从特定目录启动进程:

  1. 使用Sys.getpwd 保存当前工作目录
  2. 使用Lwt_unix.chdir切换到具体目录
  3. 使用Lwt_process.exec启动外部进程
  4. 使用Lwt_unix.chdir 切换到保存的当前工作目录

这个逻辑是有缺陷的,因为它允许调度程序在第一次调用Lwt_unix.chdir 之后和调用Lwt_process.exec 之后运行另一个线程,这将导致这个线程在特殊目录中运行 em> 而不是在保存的当前目录中。是否可以使用 Lwt 从特殊目录轻松启动进程,而不会引入我所描述的竞争条件?

【问题讨论】:

    标签: ocaml ocaml-lwt


    【解决方案1】:

    您可以使用一些同步原语来保护您当前的工作目录,例如Lwt_mutex。但是这里有一些警告,假设你有这个链:

    lock dir_guard >> chdir dir >> exec proc >> chdir dir' >> unlock dir_guard
    

    这不允许在进程proc 执行其任务的整个过程中更改目录。这可能过于谨慎和不必要。下面的代码就没有这个问题:

    let exec_in_folder guard dir proc = 
      with_lock guard (fun () -> 
         chdir dir >>= fun () -> return (exec proc)) >>= fun proc_t ->
      proc_t
    

    但是,这段代码有一个问题,只有在进程以原子方式启动时才是正确的,即,如果在进程启动过程中不存在重新调度的可能性,这将允许其他线程干扰并更改当前文件夹。为了证明它是原子的,你可以阅读源代码,或者实现你自己的进程,这将有这样的保证。如果您阅读代码,那么您会发现,该进程是使用spawn 函数创建的,该瞬间将执行fork,而没有任何穿插线程。所以是的,这段代码是正确的。

    【讨论】:

    • 感谢您的详细回答。您的exec_in_folder 函数似乎“忘记”在函数启动之前保存和恢复 cwd。我想,整个程序需要协作并使用全局互斥锁来保护 cwd,如果有一个 local 解决方案 i.e. 可以看到的解决方案会很好只需查看代码的当前部分即可。 – 我认为这应该在 Lwt 中报告为问题,你呢?
    • 是的,为了保持简洁,我已经将细节放在了范围之外。我不觉得 lwt 有任何问题(期望他们可以更好地记录process)。工作目录只是一个隐藏的全局变量。但是,在 lwt 中可以做的是,他们可以将 ?working_dir 选项添加到 exec 函数,就像 Janestreet 的人在他们的 Async 库中所做的那样。在引擎盖下,他们只是以阻塞的方式更改 cwd,因此不可能出现竞争条件。附言@Michael,抱歉回复晚了。没有提及您的评论。
    • 我的错,我忘了提到你。 :) 我在github.com/ocsigen/lwt/issues/163 中为此打开了一个问题,我想我会在接下来的几周内准备一份 PR——我现在有一个 tiiiight 时间表。 :) 自从你回答以来已经快一周了,每个人都有机会接受它,所以我会接受你的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-01
    • 2022-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多