Как писать и читать из одного и того же именованного канала в одном скрипте ruby - PullRequest
0 голосов
/ 27 февраля 2019

edit: мне кажется, я исправил проблему: https://gist.github.com/niuage/c0637b8dd10549a12b6a223dbd5f158a

Возможно, мне не хватало Process.wait, поэтому я создал много процессов-зомби.


У меня естьфрагмент кода, который работает большую часть времени, но через некоторое время «блокирует» себя, возможно, из-за состояния гонки.

Мой код

pipe = "goals.png"

(1..100).each do |time|
  fork do
    # This runs ffmpeg, and gets it to write 1 frame of a video to the pipe 'goals.png'
    print "before ffmpeg"
    `#{ffmpeg(time, score_crop_options, pipe)}`
    exit
  end

  # Reads from 'pipe'
  print "before read"
  blob = File.read(pipe)
  image = Rocket::Image.from_blob(blob)
  # do stuff with image
end

Замечания:

  • #{ffmpeg(time, pipe)} пишет в канал и блокирует, пока что-то не читает из канала

  • File.read (pipe) блокирует, пока что-то пишет в канал

Моя проблема

edit: когда скрипт заблокирован, и я пытаюсь прочитать канал из другого скрипта, я получаю zsh: fork failed: resource temporarily unavailable.Это, вероятно, хорошая подсказка ...

В большинстве случаев File.read(pipe) выполняется перед кодом в fork, поэтому он отлично работает, но через некоторое время скрипт просто останавливается: он печатает "before ffmpeg"и никогда не доберется до "before read" ...


Во-первых, я должен использовать потоки вместо fork?И могу ли я контролировать порядок запуска 2 операторов (чтение и запись), чтобы избежать условия гонки?А может, дело даже не в состоянии гонки, а я что-то упустил?

1 Ответ

0 голосов
/ 27 февраля 2019

Проблема была вызвана не состоянием гонки, а слишком большим количеством процессов-зомби, поскольку я не вызывал Process.wait

Родительский процесс должен использовать Process.wait для сбора завершения.статусы своих детей или использовать Process.detach для регистрации неинтересности в их статусе;в противном случае операционная система может накапливать процессы-зомби.

Вот почему я получаю zsh: fork failed: resource temporarily unavailable при попытке прочитать из канала другой сценарий, вероятно.

Вот что работает:

(1..100) do
  if fork
    # Parent
    image = read_image(pipe)
    # do stuff with image

    Process.wait # I think that's what was missing previously
  else
    # Child
    Open3.popen3(command(time, score_crop_options, pipe)) do |stdin, stdout, stderr, wait_thr|
      # stuff
    end
    exit!(0)
  end
end
...