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: