# Strange interference between LSAPI, popen3 and MySQL

**URL:** <https://www.ruby-forum.com/t/strange-interference-between-lsapi-popen3-and-mysql/87640>\
**Category:** Ruby\
**Created:** [March 4, 2007, 7:39pm UTC](https://www.ruby-forum.com/t/strange-interference-between-lsapi-popen3-and-mysql/87640 "2007-03-04T19:39:49Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![andreas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee7513/32.png) [@andreas](https://www.ruby-forum.com/u/andreas)\
**Post date:** [March 4, 2007, 7:39pm UTC](https://www.ruby-forum.com/t/strange-interference-between-lsapi-popen3-and-mysql/87640/1 "2007-03-04T19:39:49Z")

</div>

Hi,

I am experiencing a very strange problem in my Rails app. I use popen3  
to execute an external program. Everything works fine in Mongrel, but  
when I use the app with LSAPI, after popen3 all MySQL queries fail with  
“Mysql::Error (MySQL server has gone away)”. Once I comment out popen3  
it works fine again.

Does anyone have the slightest idea about what goes wrong here?

Thanks  
Andreas

---

<div class="post-metadata">

**Author:** ![andreas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee7513/32.png) [@andreas](https://www.ruby-forum.com/u/andreas)\
**Post date:** [March 4, 2007, 7:57pm UTC](https://www.ruby-forum.com/t/strange-interference-between-lsapi-popen3-and-mysql/87640/2 "2007-03-04T19:57:35Z")

</div>

The problem is easy to reproduce in any Rails app using LSAPI and MySQL.  
Add the following to a controller action:

```
require 'open3'
Open3.popen3('/usr/bin/ls') {|stdout, stdin, stderr| stdin.read }

```

The stdin.read is important.

---

<div class="post-metadata">

**Author:** ![andreas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee7513/32.png) [@andreas](https://www.ruby-forum.com/u/andreas)\
**Post date:** [March 4, 2007, 8:50pm UTC](https://www.ruby-forum.com/t/strange-interference-between-lsapi-popen3-and-mysql/87640/3 "2007-03-04T20:50:39Z")

</div>

On Mon, 5 Mar 2007, Andreas S. wrote:

> Hi,
> 
> I am experiencing a very strange problem in my Rails app. I use popen3  
> to execute an external program. Everything works fine in Mongrel, but  
> when I use the app with LSAPI, after popen3 all MySQL queries fail with  
> “Mysql::Error (MySQL server has gone away)”. Once I comment out popen3  
> it works fine again.
> 
> Does anyone have the slightest idea about what goes wrong here?

guessing, but popen3 uses fork. forking with and open db handle is  
undefined  
for almost any db lib - of course people ignore this. i did, and had  
all  
sorts of issues. you can read about them here

[Linux Clustering with Ruby Queue: Small Is Beautiful | Linux Journal](http://www.linuxjournal.com/article/7922)

i bet what happens is that the parent (rails) has setup an at\_exit  
handler to  
close the db on exit. when popen forks and does it’s thing in the  
child, the  
child’s death kills the db handle (at\_exit handlers being inherited - of  
course).

this shows what i’m talking about

harp:~ \> cat a.rb  
at\_exit{ puts ‘close connection **A** ’ }  
fork{ }  
Process.wait

class Object  
alias\_method ‘ **fork** ’, ‘fork’  
def fork \*a, &b  
at\_exit{ exit! }  
**fork** \*a, &b  
end  
end  
module Kernel  
alias\_method ‘ **fork** ’, ‘fork’  
def fork \*a, &b  
at\_exit{ exit! }  
**fork** \*a, &b  
end  
end

at\_exit{ puts ‘close connection **B** ’ }  
fork{ }  
Process.wait

harp:~ \> ruby a.rb  
close connection **A**

i’d try putting this

class Object  
alias\_method ‘ **fork** ’, ‘fork’  
def fork \*a, &b  
at\_exit{ exit! }  
**fork** \*a, &b  
end  
end  
module Kernel  
alias\_method ‘ **fork** ’, ‘fork’  
def fork \*a, &b  
at\_exit{ exit! }  
**fork** \*a, &b  
end  
end

in environment.rb or something. another idea, i’m grasping, is some  
sort of  
buffer flushing thing.

you could try

4242.times do |fd|  
begin  
IO.for\_fd(fd).flush  
rescue Errno::EBADF  
end  
end

right before the popen. wild ass guess though.

good luck.

-a

---

<div class="post-metadata">

**Author:** ![andreas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee7513/32.png) [@andreas](https://www.ruby-forum.com/u/andreas)\
**Post date:** [March 4, 2007, 9:43pm UTC](https://www.ruby-forum.com/t/strange-interference-between-lsapi-popen3-and-mysql/87640/4 "2007-03-04T21:43:02Z")

</div>

> > I am experiencing a very strange problem in my Rails app. I use popen3  
> > to execute an external program. Everything works fine in Mongrel, but  
> > when I use the app with LSAPI, after popen3 all MySQL queries fail with  
> > “Mysql::Error (MySQL server has gone away)”. Once I comment out popen3  
> > it works fine again.
> > 
> > Does anyone have the slightest idea about what goes wrong here?
> 
> guessing, but popen3 uses fork. forking with and open db handle is undefined  
> for almost any db lib - of course people ignore this. i did, and had all  
> sorts of issues. you can read about them here

OK, good to know. I can close the MySQL connection for the popen3 call  
and reopen it after it to avoid problems.

> i bet what happens is that the parent (rails) has setup an at\_exit handler to  
> close the db on exit.

That makes sense, although I couldn’t find any reference to at\_exit in  
Rails or ruby-lsapi.

> i’d try putting this
> 
> class Object  
> alias\_method ‘ **fork** ’, ‘fork’  
> def fork \*a, &b  
> at\_exit{ exit! }  
> **fork** \*a, &b  
> end  
> end  
> module Kernel  
> alias\_method ‘ **fork** ’, ‘fork’  
> def fork \*a, &b  
> at\_exit{ exit! }  
> **fork** \*a, &b  
> end  
> end
> 
> in environment.rb or something.

This fixes the MySQL problem (as does manually  
disconnecting/reconnecting), but now I have another problem: popen3 just  
doesn’t do anything when used within LSAPI. The program is never  
executed. Any ideas?

Who would have thought that simply calling an external program could be  
so difficult…

Thanks  
Andreas

---

<div class="post-metadata">

**Author:** ![andreas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee7513/32.png) [@andreas](https://www.ruby-forum.com/u/andreas)\
**Post date:** [March 4, 2007, 10:13pm UTC](https://www.ruby-forum.com/t/strange-interference-between-lsapi-popen3-and-mysql/87640/5 "2007-03-04T22:13:48Z")

</div>

On Mon, 5 Mar 2007, Andreas S. wrote:

> and reopen it after it to avoid problems.
> 
> > i bet what happens is that the parent (rails) has setup an at\_exit handler to  
> > close the db on exit.
> 
> That makes sense, although I couldn’t find any reference to at\_exit in  
> Rails or ruby-lsapi.

huh - maybe it’s the actuall c mysql driver.

> > ```
> > def fork *a, &b
> > 
> > ```
> 
> executed. Any ideas?  
> hmmm. no. must be related though. i’m staring to thinks it’s lsapi  
> which has  
> setup all the funky at\_exit handlers, and that this is causing you  
> grief…

> Who would have thought that simply calling an external program could be  
> so difficult…

me 😉

ultimately, in ruby queue, i had to setup a drb process before setting  
up db  
connections. then i used that drb process to do all forking/waiting for  
me.

here’s another idea, try systemu, it does not use fork at all

gem install systemu

[http://rubyforge.org/frs/?group\_id=1024&release\_id=7721](http://rubyforge.org/frs/?group_id=1024&release_id=7721)  
[http://codeforpeople.com/lib/ruby/systemu/systemu-1.0.0/README](http://codeforpeople.com/lib/ruby/systemu/systemu-1.0.0/README)

unless you need realtime control over stdin/stdout/stderr it’ll do the  
trick.

regards.

-a

---

<div class="post-metadata">

**Author:** ![andreas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee7513/32.png) [@andreas](https://www.ruby-forum.com/u/andreas)\
**Post date:** [March 4, 2007, 10:33pm UTC](https://www.ruby-forum.com/t/strange-interference-between-lsapi-popen3-and-mysql/87640/6 "2007-03-04T22:33:06Z")

</div>

Ara wrote:

> On Mon, 5 Mar 2007, Andreas S. wrote:
> 
> > > ```
> > > def fork *a, &b
> > > 
> > > ```
> > 
> > executed. Any ideas?  
> > hmmm. no. must be related though. i’m staring to thinks it’s lsapi  
> > which has  
> > setup all the funky at\_exit handlers, and that this is causing you  
> > grief…

I grepped for at\_exit in the LSAPI source code, but didn’t find  
anything. Maybe it’s the stdout/stderr/stdin redirection stuff…

> > Who would have thought that simply calling an external program could be  
> > so difficult…
> 
> me 😉
> 
> ultimately, in ruby queue, i had to setup a drb process before setting  
> up db  
> connections. then i used that drb process to do all forking/waiting for  
> me.
> 
> here’s another idea, try systemu, it does not use fork at all
> 
> gem install systemu
> 
> [http://rubyforge.org/frs/?group\_id=1024&release\_id=7721](http://rubyforge.org/frs/?group_id=1024&release_id=7721)  
> [http://codeforpeople.com/lib/ruby/systemu/systemu-1.0.0/README](http://codeforpeople.com/lib/ruby/systemu/systemu-1.0.0/README)

It seems to use popen, isn’t this based on fork, too?

The reason I want to use popen3 is not that I need stdin/stderr, but  
that there is a clean way to pass arguments without having to build a  
command line (potential escaping problems etc.).

---

<div class="post-metadata">

**Author:** ![andreas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee7513/32.png) [@andreas](https://www.ruby-forum.com/u/andreas)\
**Post date:** [March 5, 2007, 12:17am UTC](https://www.ruby-forum.com/t/strange-interference-between-lsapi-popen3-and-mysql/87640/7 "2007-03-05T00:17:03Z")

</div>

Hi~

On Mar 4, 2007, at 1:33 PM, Andreas S. wrote:

> I grepped for at\_exit in the LSAPI source code, but didn’t find
> 
> > up db
> 
> It seems to use popen, isn’t this based on fork, too?
> 
> The reason I want to use popen3 is not that I need stdin/stderr, but  
> that there is a clean way to pass arguments without having to build a  
> command line (potential escaping problems etc.).
> 
> –  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

LSAPI does its own preforking of Rails processes and disconnects and  
reconnects the database handles after every fork. The way they manage  
ruby processes causes weird issues like the one you are seeing. The  
manager code that does the fork management is closed source so it’s  
hard to know exactly what is going on in there.

Cheers-  
– Ezra Z.  
– Lead Rails Evangelist  
– removed\_email\_address@domain.invalid  
– Engine Y., Serious Rails Hosting  
– (866) 518-YARD (9273)

---

<div class="post-metadata">

**Author:** ![andreas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee7513/32.png) [@andreas](https://www.ruby-forum.com/u/andreas)\
**Post date:** [March 5, 2007, 12:46am UTC](https://www.ruby-forum.com/t/strange-interference-between-lsapi-popen3-and-mysql/87640/8 "2007-03-05T00:46:10Z")

</div>

On 3/4/07, Ezra Z. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> LSAPI does its own preforking of Rails processes and disconnects
> 
> ```
> 
> and  
> reconnects the database handles after every fork. The way they manage  
> ruby processes causes weird issues like the one you are seeing. The  
> manager code that does the fork management is closed source so it’s  
> hard to know exactly what is going on in there.

It’s all under a BSD-looking license:  
gem install ruby-lsapi

jeremy

---

<div class="post-metadata">

**Author:** ![andreas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee7513/32.png) [@andreas](https://www.ruby-forum.com/u/andreas)\
**Post date:** [March 5, 2007, 1:16am UTC](https://www.ruby-forum.com/t/strange-interference-between-lsapi-popen3-and-mysql/87640/9 "2007-03-05T01:16:13Z")

</div>

On Mar 4, 2007, at 3:45 PM, Jeremy K. wrote:

> It’s all under a BSD-looking license:  
> gem install ruby-lsapi
> 
> jeremy

You’re right, my bad. I didn’t realize they distributed the C code  
that does the management as well.

– Ezra Z.  
– Lead Rails Evangelist  
– removed\_email\_address@domain.invalid  
– Engine Y., Serious Rails Hosting  
– (866) 518-YARD (9273)

---

<div class="post-metadata">

**Author:** ![andreas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee7513/32.png) [@andreas](https://www.ruby-forum.com/u/andreas)\
**Post date:** [March 9, 2007, 9:37pm UTC](https://www.ruby-forum.com/t/strange-interference-between-lsapi-popen3-and-mysql/87640/10 "2007-03-09T21:37:42Z")

</div>

OK, we figured out what is wrong. “reopen” method need to be defined for  
“LSAPI” class since popen3 calls “reopen”. LSAPI new release will  
address this.

However, the root cause of broken MySQL connection is not LSAPI’s fault,  
actually a bug in ruby’s “open3.rb”, the fix is like:

def popen3(\*cmd)  
pw = IO::pipe # pipe[0] for read, pipe[1] for write  
pr = IO::pipe  
pe = IO::pipe

```
pid = fork{
  # child
  fork{

```

# grandchild

- 

```
begin

```

pw[1].close  
STDIN.reopen(pw[0])  
pw[0].close

pr[0].close  
STDOUT.reopen(pr[1])  
pr[1].close

pe[0].close  
STDERR.reopen(pe[1])  
pe[1].close

```
  exec(*cmd)

```

- 

```
ensure

```

- exit!(0)

- 

```
end
}
exit!(0)

```

}

pw[0].close  
pr[1].close  
pe[1].close  
Process.waitpid(pid)  
pi = [pw[1], pr[0], pe[0]]  
pw[1].sync = true  
if defined? yield  
begin  
return yield(\*pi)  
ensure  
pi.each{|p| p.close unless p.closed?}  
end  
end  
pi  
end  
module\_function :popen3  
end

Whenever an error raise in the grandchild process, this process will not  
be terminated properly, and DB connection was closed in this process,  
thus the DB connection error in the main process. It happens to both  
mongrel and LSAPI.

With above fix, DB connection is in good shape even without the LSAPI  
fix, just the command was not getting executed.

Best Regards,  
George W.

> **[LiteSpeed | Internet. Accelerated. - LiteSpeed Technologies](https://www.litespeedtech.com/)**
>
> LiteSpeed provides one-stop web-acceleration solutions that embrace and advance cutting-edge technologies. Web server, load balancer, cache solutions, and more.
