Exiting forked child closes connection in parent

7 views
Skip to first unread message

Constantin Gavrilescu

unread,
Dec 25, 2018, 11:32:35 PM12/25/18
to ruby-pg
I'm forking a new child that doesn't do any db work, but when I exit the cForking a new child 
On a debian 7.0 where the socket is in CLOSE_WAIT stastus, and in ubuntu 18.09 it is closed.
I tcpdump'ed the traffic and right when the child exits I see a FIN packet sent to the postgresql server which tells it to close the connection. I can't figure out who sends the FIN packet. Is it in the ruby-pg code or in the libpq?

>> require 'pg'; c = PG.connect('localhost', :dbname => 'postgres', :user => 'postgres')
#<PG::Connection:0x0000557f18fbe9c8>

>> s = TCPSocket.new("example.com", 80)
#<TCPSocket:fd 10, AF_INET, 192.168.0.108, 56792>

>> $$
11643

$ lsof -i -a -p 11643
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
irb     11643 costi    9u  IPv4  89040      0t0  TCP localhost:51518->localhost:postgresql (ESTABLISHED)
irb     11643 costi   10u  IPv4  98546      0t0  TCP costi-linux-zuper:56792->93.184.216.34:http (ESTABLISHED)


>> fork do end
11775

>> c.exec("select 1").to_a
Traceback (most recent call last):
        3: from /usr/bin/irb:11:in `<main>'
        2: from (irb):4
        1: from (irb):4:in `async_exec'
PG::UnableToSend (SSL connection has been closed unexpectedly)


$ lsof -i -a -p 11643
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
irb     11643 costi   10u  IPv4  98546      0t0  TCP costi-linux-zuper:56792->93.184.216.34:http (ESTABLISHED)

Jeremy Evans

unread,
Dec 26, 2018, 5:19:55 PM12/26/18
to ruby-pg
On Tuesday, December 25, 2018 at 8:32:35 PM UTC-8, Constantin Gavrilescu wrote:
I'm forking a new child that doesn't do any db work, but when I exit the cForking a new child 
On a debian 7.0 where the socket is in CLOSE_WAIT stastus, and in ubuntu 18.09 it is closed.
I tcpdump'ed the traffic and right when the child exits I see a FIN packet sent to the postgresql server which tells it to close the connection. I can't figure out who sends the FIN packet. Is it in the ruby-pg code or in the libpq?

ruby-pg, in the GC finalizer I believe.  If you fork children with an open connection, the forked child needs to call exec or it needs to call Process.exit! to exit.  The libpq documentation warns against forking after establishing a connection:  https://www.postgresql.org/docs/11/libpq-connect.html

Thanks,
Jeremy

Constantin Gavrilescu

unread,
Jan 18, 2019, 12:19:37 PM1/18/19
to ruby-pg
I can't find the finalizer in the ruby-pg source code. Can somebody point me to it?\

This is what tcpdump sees when the forked child ends:

10:30:42.387604 IP localhost.48052 > localhost.postgresql: Flags [P.], seq 402:436, ack 1546, win 377, options [nop,nop,TS val 3501900868 ecr 3501884545], length 34
10:30:42.387788 IP localhost.postgresql > localhost.48052: Flags [P.], seq 1546:1577, ack 436, win 350, options [nop,nop,TS val 3501900868 ecr 3501900868], length 31
10:30:42.387815 IP localhost.48052 > localhost.postgresql: Flags [.], ack 1577, win 377, options [nop,nop,TS val 3501900868 ecr 3501900868], length 0
10:30:42.391480 IP localhost.postgresql > localhost.48052: Flags [R.], seq 1577, ack 467, win 350, options [nop,nop,TS val 3501900872 ecr 3501900868], length 0

I see the postgresql server sending a RESET flag, but I don't see the client sending a FIN or RESET flag. It does send something, but I don't know what, there are no special flags.

Constantin Gavrilescu

unread,
Jan 18, 2019, 12:25:50 PM1/18/19
to ruby-pg
Oh I think I just found the GC free method. It's passed as a function pointer to Data_Make_Struct in pgconn_s_allocate()


static void
pgconn_gc_free( t_pg_connection *this )
{

if (this->pgconn != NULL)
PQfinish( this->pgconn );
xfree(this);
}
Reply all
Reply to author
Forward
0 new messages