将nanoc live中的fork()替换为spawn()

4

我在使用Ruby时遇到了问题,具体来说是spawn()fork()方法。

我正在Windows上使用Nanoc开发网站,在尝试实现nanoc-live gem时,我收到了一条消息,提示这台机器上未实现fork()

在研究了相关资料后,我唯一得到的建议就是用spawn()替换它。然而,我不懂Ruby,而且nanoc-live文档已经无法访问。我在支持论坛上询问过,但没有得到帮助。

我不轻易向别人请教如何解决问题,因为我喜欢自己解决问题,但这个问题让我束手无策,而我又不是一个Ruby开发者。我该如何替换下面的方法调用,以便使用spawn()?或者,如果有人有其他解决方案,那也很好。

Ruby version 3.2.2
Nanoc version 4.12.15
Windows 10

这是有问题的方法

      def run_parent
        # create initial child
        pipe_read, pipe_write = IO.pipe
        fork { run_child(pipe_write, pipe_read) { |s| yield(s) } }  Here is the method call
        pipe_read.close

        changes = gen_lib_changes
        puts 'Listening for lib/ changes…'
        changes.each do |_e|
          # stop child
          pipe_write.write('q')
          pipe_write.close
          Process.wait

          # create new child
          pipe_read, pipe_write = IO.pipe
          fork { run_child(pipe_write, pipe_read) { |s| yield(s) } }
          pipe_read.close
        end
      rescue Interrupt
      end

这是由fork()调用的run_child方法

def run_child(pipe_write, pipe_read)
        pipe_write.close

        site = Nanoc::Core::SiteLoader.new.new_from_cwd
        changes_enum = gen_changes_for_child(site)
        yield(site)

        quit = Object.new
        parent_enum = Enumerator.new do |y|
          pipe_read.read
          y << quit
        end

        puts 'Listening for site changes…'
        SlowEnumeratorTools.merge([parent_enum, changes_enum]).each do |e|
          break if quit.equal?(e)

          $stderr.print 'Reloading site… '
          $stderr.flush
          site_loader = Nanoc::Core::SiteLoader.new
          site = Nanoc::Core::Site.new(
            config: Nanoc::Core::ConfigLoader.new.new_from_cwd,
            data_source: site_loader.gen_data_source_for_config(site.config),
            code_snippets: site.code_snippets,
          )
          $stderr.puts 'done'

          yield(site)
        end

        exit 0
      rescue Interrupt
        exit 0
      end

提前致谢。

2个回答

1

所有相关的问题只是让我更加怀疑人生,不过还是谢谢您。更改生产源代码以使用线程以实现 Windows 兼容性。唉。 - TechnicalTophat
所有这些关联的问题只是让我更多地质疑生活。但还是谢谢。修改生产源代码以使用线程来提高Windows兼容性。叹气。 - TechnicalTophat
所有相关的问题只是让我更加质疑人生。但还是谢谢。正在修改生产源代码以使用线程来提高Windows兼容性。唉。 - undefined

1

首先,Linux支持“forking”,但Windows不支持;Windows只支持“spawning”:

  • “forking” = 父进程创建一个自身的副本(子进程),该子进程具有完全相同的所有内存段

  • “spawning” = 父进程创建一个全新的子进程,它不共享父进程的内存,并且父进程必须等待子进程完成后才能继续

明确一点,这是一个与Windows操作系统整体相关的问题,与任何特定的编程语言无关,包括Ruby。例如,当使用Python时,我在这里链接遇到了一个相关问题。

因此,由@amycodes提供的链接中的答案不幸地包含准确的信息。

要模仿`fork`,你需要`spawn`一个新的进程/线程,然后将数据复制到新的进程/线程中。你还需要检查你的数据是否可以以线程安全的方式复制(例如,在Python中,生成器不能跨进程边界进行编组,并且你在源代码中使用了`yield`,这让我觉得你想做的事情可能不可能实现)。由于你正在用一个进程/线程创建加上复制来替换Linux操作系统中的内置操作,请注意这将比在Linux上运行得更慢(这是使用Windows所付出的代价)。
我对Ruby并不是特别熟悉,所以希望有其他人能够核对我的答案。
(祝你好运,朋友!)

请勿在您的回答中包含ChatGPT的响应。即使您承认以下内容是由AI生成的,这也是严格禁止的。 - zenly
@zenly 我没有意识到,我会将其删除。您能否详细说明为什么禁止使用ChatGPT?是否有stackoverflow的规则/指南明确说明了这一点? - A. Hendry
它被固定在右侧的“Hot Meta Posts”下方:https://meta.stackoverflow.com/questions/421831/temporary-policy-chatgpt-is-banned?cb=1 - zenly
1
它被固定在右侧的“热门元帖”下方:https://meta.stackoverflow.com/questions/421831/temporary-policy-chatgpt-is-banned?cb=1 - kelsny
1
它被固定在右侧的“热门元帖”下方:https://meta.stackoverflow.com/questions/421831/temporary-policy-chatgpt-is-banned?cb=1 - undefined
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接