Fork

I want to fork a child process and use instantiated objects from the
parent
process. Is this possible?

obj = Object.new

fork do
doSomething(obj)
end

Joey M. wrote:

I want to fork a child process and use instantiated objects from the parent
process. Is this possible?

obj = Object.new

fork do
doSomething(obj)
end

Yes, but it is a copy of the original, so modifications in the child
don’t affect the parent.

Joey M. wrote:

I want to fork a child process and use instantiated objects from the
parent
process. Is this possible?

obj = Object.new

fork do
doSomething(obj)
end

class Dog
def greet
puts ‘hello’
end
end

d = Dog.new

fork do
d.greet
end

Process.wait

–output:–
hello

I see,
I have a class to handle interfacing to the database. The initialization
of
the class will connect to the db and another method will close the
connection and there are query functions for handling the queries and
results. This object is then passed into new objects on their
initialization. The problem comes in when I iterate through a set of
objects
creating a fork for each one. After the first object I am getting a
“database went away error”. My code looks like the following:

db = MySQL.new

fork do
obj1 = Object1.new(db)
obj1.addToDb
end
Process.wait

fork do
obj2 = Object2.new(db) #Object1 and Object2 are inherited from the
same
superclass
ob2.addToDb #db error occurs here
end
Process.wait

db.closeDB

–output–
obj1 info added to db!
Error message: MySQL server has gone away

I know I am missing a key concept here. This is the first time I have
worked
with forked processes.

On Wed, Mar 26, 2008 at 7:39 PM, Joel VanderWerf
[email protected]

Is tonight UNIX night? :slight_smile:

On Wed, Mar 26, 2008 at 6:09 PM, Joey M. [email protected]
wrote:

superclass
ob2.addToDb #db error occurs here
end
Process.wait

When you fork you create a new process. When you reach the “end” of
the block, that process exits. My guess is that when your code passes
the first Process.wait, your MySQL object was torn down by the dieing
process.

Look at this code:

#!/usr/bin/env ruby

END { puts “Bye from #{Process.pid}” }

fork do
puts “Hello from #{Process.pid}”
end

Process.wait

fork do
puts “Hello from #{Process.pid}”
end

Process.wait

What do you expect to see when you run it?

Marcelo

Joey M. wrote:

fork do
obj1 = Object1.new(db)
obj1.addToDb

At this point in the child, the process is about to exit, the db object
in the child is freed, and (my guess) a finalizer is executed which
closes the database connection.

end
Process.wait

fork do
obj2 = Object2.new(db) #Object1 and Object2 are inherited from the same
superclass
ob2.addToDb #db error occurs here

…which is the same as the connection you’re trying to use here (same
connection because of the fork), through this copy of the db object.

But that’s only my guess. I don’t know how the MySQL ruby interface
works, or if there is a way to tell it not to close the connection when
the child exits.

Possibly informative:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/117013

If you really need the forks to access the database, they could start
new connections. If there’s a performance problem with that, you could
keep a pool of child processes and send them commands from the parent.
(The slave gem might be a good way to do that.)

2008/3/27, Joey M. [email protected]:

I have a class to handle interfacing to the database. The initialization of
the class will connect to the db and another method will close the
connection and there are query functions for handling the queries and
results. This object is then passed into new objects on their
initialization.

This cannot possibly work, as you have discovered. You need to open
DB connections in child processes individually because there are
usually socket connections involved and you cannot share the same
connection between processes because the DB needs to keep them
separate even though you can share the client socket.

The problem comes in when I iterate through a set of objects
creating a fork for each one. After the first object I am getting a
“database went away error”. My code looks like the following:

I know I am missing a key concept here. This is the first time I have worked
with forked processes.

See above.

Kind regards

robert

Joel VanderWerf wrote:

Joey M. wrote:

I want to fork a child process and use instantiated objects from the parent
process. Is this possible?

obj = Object.new

fork do
doSomething(obj)
end

Yes, but it is a copy of the original, so modifications in the child
don’t affect the parent.

Who said anyting about modifying the original? The post reads:

I want to fork a child process and use instantiated objects from the
parent

On Wed, 26 Mar 2008 19:09:10 -0500, Joey M. wrote:

I want to fork a child process and use instantiated objects from the
parent
process. Is this possible?

Yes, but it is a copy of the original, so modifications in the child
don’t affect the parent.

[Note: parts of this message were removed to make it a legal post.]

I see,
I have a class to handle interfacing to the database. The initialization
of the class will connect to the db and another method will close the
connection and there are query functions for handling the queries and
results. This object is then passed into new objects on their
initialization. The problem comes in when I iterate through a set of
objects creating a fork for each one. After the first object I am
getting a “database went away error”. My code looks like the following:

When you fork() a new process, both the memory is copied, but both the
parent and child processes share the same open files, including the same
socket (because there’s no real concept of duplicating the socket at
both
ends). When one process quits, it closes the connection automatically
(this is done by a finalizer on the database handle, or something like
that, possibly buried in the C library). In the MySQL protocol[1], this
sends a command over the socket to the MySQL server, and the server and
client close their connection. The second process, which still has the
socket open, now discovers that the connection is closed and reports
that
the server has gone away.

A good solution to this problem is to fork a DRb server that serves up
the database access stuff, and allocate the Mysql connection only inside
that process. DRb connections will work just fine across forks.

(I know I implemented this before, but I can’t find the sample code.)

–Ken

[1] http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol

On Wed, 26 Mar 2008 19:09:10 -0500, Joey M. wrote:

[Note: parts of this message were removed to make it a legal post.]

I see,
I have a class to handle interfacing to the database. The initialization
of the class will connect to the db and another method will close the
connection and there are query functions for handling the queries and
results. This object is then passed into new objects on their
initialization. The problem comes in when I iterate through a set of
objects creating a fork for each one. After the first object I am
getting a “database went away error”.

Here we go. Here’s my sample code for solving this issue.

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/204151

–Ken