Conflicts between Local Connections and Child Process Handling on Unix
Background
When a local (not-TCP) Oracle connection is established on Unix, Oracle client library changes signal handlers in the process to reap all dead child processes. However it conflicts with child process handling in ruby.
Problem 1: It trashes child process handling of Open3::popen.
require 'oci8'
require 'open3'
Open3::popen3('true') do |i, o, e, w|
p w.value
end
conn = OCI8.new(username, password)
puts "establish a local connection"
Open3::popen3('true') do |i, o, e, w|
p w.value
end
The above code outputs the following result:
#<Process::Status: pid 19236 exit 0>
establish a local connection
nil
w.value after a local connection doesn't work because Oracle reaps
the child process on the process termination before ruby detects it.
Problem 2: It creates defunct processes after disconnection if signal handlers are reset.
The system function overwrites signal handlers.
It fixes the problem 1 as follows.
require 'oci8'
require 'open3'
Open3::popen3('true') do |i, o, e, w|
p w.value
end
conn = OCI8.new(username, password) # Signal handlers are changed here.
puts "establish a local connection"
system('true') # Signal handlers are reset here.
Open3::popen3('true') do |i, o, e, w|
p w.value
end
The above code outputs the following result:
#<Process::Status: pid 19652 exit 0>
establish a local connection
#<Process::Status: pid 19656 exit 0>
w.value after a local connection works.
However it makes another problem.
require 'oci8'
conn = OCI8.new(username, password) # Signal handlers are changed here.
# An Oracle server process is created here.
puts "establish a local connection"
system('true') # Signal handlers are reset here.
conn.logoff # The Oracle server process exits and become defunct.
# ... do other stuffs...
If a program repeatedly creates a local connection and disconnects it, the number of defunct processes increases gradually.
Solution: BEQUEATH_DETACH=YES
By setting BEQUEATH_DETACH=YES in sqlnet.ora, Oracle client library
doesn't change signal handlers. The above two problems are fixed.
Oracle client library reads sqlnet.ora in the following locations:
$TNS_ADMIN/sqlnet.oraif the environment variableTNS_ADMINis set and$TNS_ADMIN/sqlnet.oraexists. Otherwise,$ORACLE_HOME/network/admin/sqlnet.ora.$HOME/.sqlnet.ora