Thread: libpgtcl: pq_recvbuf: unexpected EOF on client connection

libpgtcl: pq_recvbuf: unexpected EOF on client connection

From
g.hintermayer@inode.at (Gerhard Hintermayer)
Date:
I constantly keep getting this message in the log files when
disconnection with pg_disconnect (TCL-interface) I did an upgrade to
7.2.1 in combination with Tcl8.3.4, everything works, but that message
is annoying. Using psql doesn't produce any log entrys.
Even a simple script
set conn [pg_connect ....]
pg_disconnect $conn

creates the log entry. Has anyone ever encountered that problem ?

Gerhard

-- 
Gerhard Hintermayer
http://www.inode.at/g.hintermayer


Re: libpgtcl: pq_recvbuf: unexpected EOF on client connection

From
Tom Lane
Date:
g.hintermayer@inode.at (Gerhard Hintermayer) writes:
> I constantly keep getting this message in the log files when
> disconnection with pg_disconnect (TCL-interface)

Yeah, I see it too --- though everything's fine if you just exit the
client program without an explicit pg_disconnect.  I think the problem
is that pg_disconnect shouldn't be unregistering the notifier_channel;
I bet TCL thinks it should close the socket when we do that.  Then
the later PQfinish call will be unable to send the normal termination
message to the backend.  Probably the best fix is to move the unregister
call into PgDelConnectionId(), after we do PQfinish.
        regards, tom lane


Re: libpgtcl: pq_recvbuf: unexpected EOF on client connection

From
Gerhard Hintermayer
Date:
Tom Lane wrote:
> g.hintermayer@inode.at (Gerhard Hintermayer) writes:
> 
>>I constantly keep getting this message in the log files when
>>disconnection with pg_disconnect (TCL-interface)
> 
> 
> Yeah, I see it too --- though everything's fine if you just exit the
> client program without an explicit pg_disconnect.  I think the problem
> is that pg_disconnect shouldn't be unregistering the notifier_channel;
> I bet TCL thinks it should close the socket when we do that.  Then
> the later PQfinish call will be unable to send the normal termination
> message to the backend.  Probably the best fix is to move the unregister
> call into PgDelConnectionId(), after we do PQfinish.
> 
>             regards, tom lane

Hope my posting works.

I don't understand what you're thinking of, because the unregistering triggers 
the call to PgDelConnectionId, so who will close the connection if you remove 
the unregister call ?
I wonder what has changed either in the Tcl or the PQ internals, since this 
worked in Tcl8.3.2 combined with PostgreSQL 7.0.2. Going to check that tomorrow 
at work.
Btw, is the PQfinish syncroneous (?) or not ? Maybe the problem is we're sending 
the X and close the connection immediately instead of letting the server close it.

Gerhard

-- 
Gerhard Hintermayer
http://www.inode.at/g.hintermayer



Re: libpgtcl: pq_recvbuf: unexpected EOF on client connection

From
Tom Lane
Date:
Gerhard Hintermayer <g.hintermayer@inode.at> writes:
> I don't understand what you're thinking of, because the unregistering
> triggers the call to PgDelConnectionId, so who will close the
> connection if you remove the unregister call ?

I meant the unregister of the notifier_channel, which is not
Pg_disconnect's business anyway.  Unfortunately, it seems this fixes
your problem but creates a bigger one: Tcl dumps core if you shut down
the interpreter without having done pg_disconnect.

As a compromise I've applied the attached patch, which seems to suppress
the "unexpected EOF" problem at the cost of leaking a small amount of
memory for each disconnect.
        regards, tom lane

*** src/interfaces/libpgtcl/pgtclCmds.c.orig    Mon Sep  2 17:51:47 2002
--- src/interfaces/libpgtcl/pgtclCmds.c    Mon Sep  2 18:03:35 2002
***************
*** 399,405 **** int Pg_disconnect(ClientData cData, Tcl_Interp *interp, int argc, char *argv[]) {
-     Pg_ConnectionId *connid;     PGconn       *conn;     Tcl_Channel conn_chan; 
--- 399,404 ----
***************
*** 413,427 ****     if (conn_chan == NULL)     {         Tcl_ResetResult(interp);
!         Tcl_AppendResult(interp, argv[1], " is not a valid connection\n", 0);         return TCL_ERROR;     } 
! #if TCL_MAJOR_VERSION >= 8
!     conn = PgGetConnectionId(interp, argv[1], &connid);
!     if (connid->notifier_channel != NULL)
!         Tcl_UnregisterChannel(interp, connid->notifier_channel);
! #endif      return Tcl_UnregisterChannel(interp, conn_chan); }
--- 412,425 ----     if (conn_chan == NULL)     {         Tcl_ResetResult(interp);
!         Tcl_AppendResult(interp, argv[1], " is not a valid connection", 0);         return TCL_ERROR;     } 
!     /* Check that it is a PG connection and not something else */
!     conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId **) NULL);
!     if (conn == (PGconn *) NULL)
!         return TCL_ERROR;      return Tcl_UnregisterChannel(interp, conn_chan); }
*** src/interfaces/libpgtcl/pgtclId.c.orig    Mon Sep  2 17:51:47 2002
--- src/interfaces/libpgtcl/pgtclId.c    Mon Sep  2 19:38:22 2002
***************
*** 193,199 ****  #if TCL_MAJOR_VERSION >= 8     connid->notifier_channel = Tcl_MakeTcpClientChannel((ClientData)
PQsocket(conn));
!     Tcl_RegisterChannel(interp, connid->notifier_channel); #else     connid->notifier_socket = -1; #endif
--- 194,200 ----  #if TCL_MAJOR_VERSION >= 8     connid->notifier_channel = Tcl_MakeTcpClientChannel((ClientData)
PQsocket(conn));
!     Tcl_RegisterChannel(NULL, connid->notifier_channel); #else     connid->notifier_socket = -1; #endif
***************
*** 286,291 ****
--- 289,313 ----     connid->conn = NULL;      /*
+      * Kill the notifier channel, too.  We must not do this until after
+      * we've closed the libpq connection, because Tcl will try to close
+      * the socket itself!
+      *
+      * XXX Unfortunately, while this works fine if we are closing due to
+      * explicit pg_disconnect, Tcl versions through 8.3.3 dump core if we
+      * try to do it during interpreter shutdown.  Not clear why, or if
+      * there is a workaround.  For now, accept leakage of the (fairly
+      * small) amount of memory taken for the channel state representation.
+      * Note we are not leaking a socket, since libpq closed that already.
+      */
+ #ifdef NOT_USED
+ #if TCL_MAJOR_VERSION >= 8
+     if (connid->notifier_channel != NULL)
+         Tcl_UnregisterChannel(NULL, connid->notifier_channel);
+ #endif
+ #endif
+ 
+     /*      * We must use Tcl_EventuallyFree because we don't want the connid      * struct to vanish instantly if
Pg_Notify_EventProcis active for it.      * (Otherwise, closing the connection from inside a pg_listen callback