在子进程之后读取输入在Ruby shell中接收SIGTSTP

时间:2015-02-26 03:30:47

标签: ruby shell unix signals

下面的ruby代码显示一个问题,即在其子进程被暂停后恢复的父进程(SIGTSTP)在输入字符之后才会实际接收输入。

以下是使用以下代码重现的步骤:

  • 运行以下repl.rb,除非您输入“irb”,否则将回显您打印的内容。
  • 输入“irb”以启动新的irb流程。
  • 按Ctrl-Z发送SIGTSTP以停止irb进程。
  • 你将被带回主要的代表。甚至提供了一个提示。
  • 输入“foo”,按回车键。你会被回应“oo”。
  • 再次输入“foo”,按回车键。你会看到“foo”。
  • 键入“exit”退出程序。一旦你的程序退出,将打印丢失的“f”。
  • 为什么第一个“f”在第一次出现并且在程序退出后才会出现?

以下是repl.rb的来源:

Signal.trap("SIGTSTP", "IGNORE")

pids = []
stty_save = `stty -g`
loop do
  print "#{$0}> "
  input = STDIN.gets.chomp
  if input == "exit"
    exit
  else
    command = nil
    if input == "irb"
      command = "irb"
    elsif input == "fg" && pids.last
      Process.kill "SIGCONT", pids.last
    else
      puts input
      next
    end
    if command
      pid = fork do
        Signal.trap("SIGTSTP", "DEFAULT")
        exec command
      end
      pids << pid
    end
    pid, status = Process.waitpid2 pids.last, Process::WUNTRACED if pids.last
    if status.stopsig == 18 # stopped
      system "stty", stty_save
      puts "Stopped"
    else
      pids.pop
    end
  end
end

这是我得到的:

/tmp  ➜ ruby repl.rb
repl.rb> foo
foo
repl.rb> irb
>> Stopped
repl.rb> foo
oo
repl.rb> exit
f/tmp  ➜

这就是我的预期:

/tmp  ➜ ruby repl.rb
repl.rb> foo
foo
repl.rb> irb
>> Stopped
repl.rb> foo
foo
repl.rb> exit
/tmp  ➜

更新

这适用于Linux(或至少Ubuntu 14.04.1)。我的主机出现问题的是运行Yosemite的OS X.

在Linux上,父进程接收信号编号20而不是18(如在OS X上)。

0 个答案:

没有答案