bug in libpgtcl listen - Mailing list pgsql-hackers

From Massimo Dal Zotto
Subject bug in libpgtcl listen
Date
Msg-id 199901081541.QAA04318@nikita.wizard.net
Whole thread Raw
Responses Re: [HACKERS] bug in libpgtcl listen
List pgsql-hackers
Hi,

I found a bug in the notify handler of the libpgtcl interface.
If I have setup a notify handler and the backend dies, the tcl interpreter
will not remove the handler and loop forever with a bad fd in select().
I tested the bug with Tcl7.5 and the following code:

$ wish
% set tcl_version
7.5
% set tk_version
4.1
% source pg_test.tcl
% connect dz
pgsql4
% sql select 123
123
% listen
% notify
% --> callback test

# From another shell kill the backend:
$ kill 3937

# Now the wish shell is looping forever in the following syscall:
$ strace -p 3934
select(5, [0 3 4], [], [], NULL)        = -1 EBADF (Bad file number)
select(5, [0 3 4], [], [], NULL)        = -1 EBADF (Bad file number)
select(5, [0 3 4], [], [], NULL)        = -1 EBADF (Bad file number)
select(5, [0 3 4], [], [], NULL)        = -1 EBADF (Bad file number)
select(5, [0 3 4], [], [], NULL)        = -1 EBADF (Bad file number)
...

# The fd 4 doesn't exists anymore because it has been closed by pqReadData.
$ ls -l /proc/3934/fd
total 0
lrwx------   1 dz       users          64 Jan  8 16:00 0 -> [0801]:2081
lrwx------   1 dz       users          64 Jan  8 16:00 1 -> [0801]:2081
lrwx------   1 dz       users          64 Jan  8 16:00 2 -> [0801]:2081
lrwx------   1 dz       users          64 Jan  8 16:00 3 -> [0000]:12617

This is the test file loaded in the above example:

# pg_test.tcl -- 
#
# Test libpgtcl interface

load libpgtcl.so.2

proc connect {{db dz}} {   global conn   set conn [pg_connect $db]
}

proc sql {args} {   global conn   if {$args != {}} {       set cmd $args   } else {       set cmd "select 1"   }   set
res[pg_exec $conn $cmd]   switch [pg_result $res -status] {       PGRES_TUPLES_OK {           for {set n 0} {$n <
[pg_result$res -numTuples]} {incr n} {               puts [pg_result $res -getTuple $n]           }       }
PGRES_COMMAND_OK{}       default {           puts [pg_result $res -status]       }   }   pg_result $res -clear
 
}

proc disconnect {} {   global conn   pg_disconnect $conn   set conn {}
}

proc listen {{relname test}} {   global conn   pg_listen $conn $relname "callback $relname"
}

proc unlisten {{relname test}} {   global conn   pg_listen $conn $relname {}
}

proc notify {{relname test}} {   global conn   sql notify $relname
}

proc callback {args} {   puts "--> callback $args"
}

# end of file


The following patch seems to fix the problem:

*** src/interfaces/libpgtcl/pgtclId.c.orig    Mon Sep 21 03:02:03 1998
--- src/interfaces/libpgtcl/pgtclId.c    Fri Jan  8 16:27:51 1999
***************
*** 638,649 **** Pg_Notify_FileHandler (ClientData clientData, int mask) {     Pg_ConnectionId *connid =
(Pg_ConnectionId*) clientData;      /*      * Consume any data available from the SQL server (this just buffers      *
itinternally to libpq; but it will clear the read-ready condition).      */
 
!     PQconsumeInput(connid->conn);      /* Transfer notify events from libpq to Tcl event queue. */
PgNotifyTransferEvents(connid);
--- 638,656 ---- Pg_Notify_FileHandler (ClientData clientData, int mask) {     Pg_ConnectionId *connid =
(Pg_ConnectionId*) clientData;
 
+     int status;      /*      * Consume any data available from the SQL server (this just buffers      * it internally
tolibpq; but it will clear the read-ready condition).
 
+      *
+      * Must check the connection status and stop the event source for
+      * closed connection. -- dz      */
!     status = PQconsumeInput(connid->conn);
!     if (status == 0) {
!         PgStopNotifyEventSource(connid);
!     }      /* Transfer notify events from libpq to Tcl event queue. */     PgNotifyTransferEvents(connid);

-- 
Massimo Dal Zotto

+----------------------------------------------------------------------+
|  Massimo Dal Zotto               email: dz@cs.unitn.it               |
|  Via Marconi, 141                phone: ++39-0461534251              |
|  38057 Pergine Valsugana (TN)      www: http://www.cs.unitn.it/~dz/  |
|  Italy                             pgp: finger dz@tango.cs.unitn.it  |
+----------------------------------------------------------------------+


pgsql-hackers by date:

Previous
From: Massimo Dal Zotto
Date:
Subject: some patches for 6.4.2
Next
From: Bruce Momjian
Date:
Subject: Re: EXCEPT/INTERSECT for v6.4