# Forking and copying variables

**URL:** <https://www.ruby-forum.com/t/forking-and-copying-variables/91152>\
**Category:** Ruby\
**Created:** [April 5, 2007, 6:03am UTC](https://www.ruby-forum.com/t/forking-and-copying-variables/91152 "2007-04-05T06:03:40Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![metrix](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/48db29/32.png) [@metrix](https://www.ruby-forum.com/u/metrix)\
**Post date:** [April 5, 2007, 6:03am UTC](https://www.ruby-forum.com/t/forking-and-copying-variables/91152/1 "2007-04-05T06:03:40Z")

</div>

I have a script that sets a few variables and then forks. Each fork  
executes the script from top to bottom. Is there any way for the forks  
to get a copy of all the variables set before the fork, because each  
fork thinks it;s running for the first time (and ya I see why because a  
fork is a copy of the current process)?

Maybe forking isn’t what I’m looking for, but the performance is so much  
better than threading for this task.

Thanks for reading.

---

<div class="post-metadata">

**Author:** ![metrix](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/48db29/32.png) [@metrix](https://www.ruby-forum.com/u/metrix)\
**Post date:** [April 5, 2007, 6:41am UTC](https://www.ruby-forum.com/t/forking-and-copying-variables/91152/2 "2007-04-05T06:41:22Z")

</div>

I see!

I am on Windows. I was hoping to write something that would work on both  
Windows and Linux so I tried to keep things simple by only using  
Process.fork.

I’ll read a little more on Win32 Process.create and see if this can get  
me what I need. If so I can detect the platform and fork the appropriate  
way on Linux or Windows.

---

<div class="post-metadata">

**Author:** ![metrix](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/48db29/32.png) [@metrix](https://www.ruby-forum.com/u/metrix)\
**Post date:** [April 5, 2007, 6:20am UTC](https://www.ruby-forum.com/t/forking-and-copying-variables/91152/3 "2007-04-05T06:20:50Z")

</div>

Brandon C. wrote:

> 

Are you using the win32/process version of fork? If so, what you are  
seeing is one of the differences between that and native fork on  
unix/linux.

For example, this code:

puts “foop”

Process.fork do  
puts “fork”  
end

on linux produces the following output:

foop  
fork

and on windows (requiring ‘win32/process’ first) produces:

foop  
foop  
fork

---

<div class="post-metadata">

**Author:** ![metrix](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/48db29/32.png) [@metrix](https://www.ruby-forum.com/u/metrix)\
**Post date:** [April 5, 2007, 7:10am UTC](https://www.ruby-forum.com/t/forking-and-copying-variables/91152/4 "2007-04-05T07:10:00Z")

</div>

On Apr 5, 2007, at 12:19 AM, Joel VanderWerf wrote:

> end  
> fork  
> This seems like a typical IO buffering problem rather than  
> different semantics regarding process data shared across  
> forks.

It looks like in the Windows version stdout is buffered such  
that ‘foop’ is not written before the fork. After the fork  
the output buffer still has ‘foop\n’ in it. At some point  
the parent flushes its buffer (with just ‘foop\n’) and then  
later the child flushes its buffer (with ‘foop\nfork\n’)  
giving you the result you see.

This is a common ‘gotcha’ in Unix if stdout is going to  
a file and so it isn’t line buffered. If stdout goes to  
a terminal device it is line buffered and so the problem  
doesn’t occur since each call to puts flushes a line of  
output.

I’m not a Windows guy but that’s what seems to be happening  
in Joel’s example.

I’m still not sure what problem the original poster is  
encountering. Some sample code and output would help.

Gary W.

---

<div class="post-metadata">

**Author:** ![metrix](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/48db29/32.png) [@metrix](https://www.ruby-forum.com/u/metrix)\
**Post date:** [April 5, 2007, 10:21am UTC](https://www.ruby-forum.com/t/forking-and-copying-variables/91152/5 "2007-04-05T10:21:19Z")

</div>

On 05.04.2007 06:03, Brandon C. wrote:

> I have a script that sets a few variables and then forks. Each fork  
> executes the script from top to bottom. Is there any way for the forks  
> to get a copy of all the variables set before the fork, because each  
> fork thinks it;s running for the first time (and ya I see why because a  
> fork is a copy of the current process)?
> 
> Maybe forking isn’t what I’m looking for, but the performance is so much  
> better than threading for this task.

Use the block form of fork, that will preserve all state:

10:14:12 [~]: ruby -e ‘p $$; foo=1; 2.times do fork do  
while foo \< 10  
print $$, “:”, foo, “\n”  
foo+=1  
end  
end end’  
3840  
3468:1  
3468:2  
3468:3  
3468:4  
3468:5  
3468:6  
3468:7  
3468:8  
3468:9  
10:14:42 [~]: 3600:1  
3600:2  
3600:3  
3600:4  
3600:5  
3600:6  
3600:7  
3600:8  
3600:9

10:14:54 [~]:

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![metrix](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/48db29/32.png) [@metrix](https://www.ruby-forum.com/u/metrix)\
**Post date:** [April 5, 2007, 8:56pm UTC](https://www.ruby-forum.com/t/forking-and-copying-variables/91152/6 "2007-04-05T20:56:28Z")

</div>

Gary W. wrote:

> > Process.fork do  
> > foop  
> > the output buffer still has ‘foop\n’ in it. At some point  
> > I’m not a Windows guy but that’s what seems to be happening  
> > in Joel’s example.
> 
> I’m still not sure what problem the original poster is  
> encountering. Some sample code and output would help.

The source for win32/process makes it clear what is going on:

```
   cmd = 'ruby -I "' + $LOAD_PATH.join(File::PATH_SEPARATOR) << '" 

```

“’  
cmd \<\< File.expand\_path($PROGRAM\_NAME) \<\< '” ’ \<\< ARGV.join(’ ‘)  
cmd \<\< ’ child#’ \<\< @child\_pids.length.to\_s

```
   startinfo = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
   startinfo = startinfo.pack('LLLLLLLLLLLLSSLLLL')
   procinfo = [0,0,0,0].pack('LLLL')

   rv = CreateProcess(0, cmd, 0, 0, 1, 0, 0, 0, startinfo, procinfo)

```

It runs the same ruby script again in another process. It’s not really  
fork in the unix sense.

---

<div class="post-metadata">

**Author:** ![metrix](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/48db29/32.png) [@metrix](https://www.ruby-forum.com/u/metrix)\
**Post date:** [April 5, 2007, 9:14pm UTC](https://www.ruby-forum.com/t/forking-and-copying-variables/91152/7 "2007-04-05T21:14:31Z")

</div>

On Apr 5, 2007, at 2:54 PM, Joel VanderWerf wrote:

> ```
> rv = CreateProcess(0, cmd, 0, 0, 1, 0, 0, 0, startinfo,  
> 
> ```
> 
> procinfo)
> 
> It runs the same ruby script again in another process. It’s not  
> really fork in the unix sense.

Thanks for clarifying things Joel. As I said, I’m not a Windows guy…

Seems like a bad choice to use the name ‘fork’ for this behavior.  
It is more like a fork/exec of the original script (in Unix  
terminology). It would make more sense to me to have Process.fork  
fail with an exception on Windows and come up with a different name  
for this Windows-only behavior.

The pseudo-portability of Ruby code has always seemed a bit odd to  
me. Obviously this sort of issue comes up with File IO, OS services,  
process and thread semantics and so on.

I almost wish that the differences were more obvious via the class  
structure rather than methods of the same class having different  
semantics on different platforms.

Gary W.

---

<div class="post-metadata">

**Author:** ![metrix](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/48db29/32.png) [@metrix](https://www.ruby-forum.com/u/metrix)\
**Post date:** [April 5, 2007, 9:03pm UTC](https://www.ruby-forum.com/t/forking-and-copying-variables/91152/8 "2007-04-05T21:03:29Z")

</div>

On Apr 5, 2007, at 4:20 AM, Robert K. wrote:

> > better than threading for this task.
> 
> Use the block form of fork, that will preserve all state:

I don’t think the state preserving semantics are different for block or  
non-block forms:

$ cat fork.rb  
foo = 1

if child = Process.fork  
puts “parent says: child is pid #{child}, foo is #{foo}”  
else  
puts “child says: my pid is #{$$}, foo is #{foo}”  
end

$ ruby fork.rb  
child says: my pid is 7875, foo is 1  
parent says: child is pid 7875, foo is 1

Gary W.

---

<div class="post-metadata">

**Author:** ![metrix](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/48db29/32.png) [@metrix](https://www.ruby-forum.com/u/metrix)\
**Post date:** [April 5, 2007, 9:22pm UTC](https://www.ruby-forum.com/t/forking-and-copying-variables/91152/9 "2007-04-05T21:22:31Z")

</div>

Gary W. wrote:

> > ```
> > procinfo = [0,0,0,0].pack('LLLL')
> > 
> > ```
> 
> terminology). It would make more sense to me to have Process.fork  
> fail with an exception on Windows and come up with a different name  
> for this Windows-only behavior.
> 
> The pseudo-portability of Ruby code has always seemed a bit odd to  
> me. Obviously this sort of issue comes up with File IO, OS services,  
> process and thread semantics and so on.
> 
> I almost wish that the differences were more obvious via the class  
> structure rather than methods of the same class having different  
> semantics on different platforms.

I agree with all of the above. What the win32 fork does is useful in its  
own way, and it might even be useful to have something on unix/linux  
that has the same semantics (fork/exec original script). But it needs a  
different name…
