fork

J

Joey Marino

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

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
 
7

7stud --

Joey said:
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
 
J

Joel VanderWerf

Joey said:
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.
 
J

Joey Marino

[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:

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.
 
J

Joel VanderWerf

Joey said:
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

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.)
 
M

Marcelo

Is tonight UNIX night? :)

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

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
 
7

7stud --

Joel said:
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:
 
R

Robert Klemme

2008/3/27 said:
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
 
K

Ken Bloom

[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
 
K

Ken Bloom

[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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,158
Latest member
Vinay_Kumar Nevatia
Top