0

I have the following ruby shell.

#!/usr/bin/env ruby

$stdin.each_line do |line|
  pid = fork{
    exec line
    puts "after exec -> #{Process.pid}"
  }
  Process.wait pid
end

The puts method after exec is never executed. Based on ri Kernel.exec, it seems that exec replaces the current process by running the given external. So, it's supposed to replace the new forked processes with the external processes. How am I supposed to run anything after exec command?

sawa
  • 165,429
  • 45
  • 277
  • 381
Eki Eqbal
  • 5,779
  • 9
  • 47
  • 81

1 Answers1

3

You cannot.

Per the documentation for Kernel#exec, "[it] replaces the current process by running the given external command". That means that you are no longer running your code but instead the code you specified by the command.

If you want to "wrap" a system call then you should use Kernel#system (or the backtick operator) to execute the command in a subshell.

maerics
  • 151,642
  • 46
  • 269
  • 291
  • In other words, don't pull the ripcord if you're not done. Also, `system` is preferable to the backticks style as it makes it abundantly clear what you're doing. – tadman Sep 25 '13 at 18:43
  • But is there any workaround for this? what if I want to run some external command and then modify the results? Any help would be appreciated. – Eki Eqbal Sep 25 '13 at 18:44
  • As context, this is actually central to the way the Unix process model works. There *is* no primitive call that starts a new process with a different program. Instead, a process `fork`s itself into two copies of the same program, and one of them `exec`s, turning into the new program. When it forks, it can set up a line of communication (a pipe) between the parent and child. That's what the backtick operator does for you: builds a pipe, `fork`s, and `exec`s. – Peeja Sep 25 '13 at 19:04