mirror of
https://github.com/postgres/postgres.git
synced 2025-05-24 00:03:23 -04:00
Partial solution for 'unexpected EOF' problem with pg_disconnect: it
seems we have a choice between annoying messages and leaking memory (or dumping core, but that's right out). Patch also fixes several other problems in pg_disconnect, such as being willing to close a channel that isn't a PG channel.
This commit is contained in:
parent
b28b05317d
commit
00482fde8e
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.66 2002/09/02 21:51:47 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.67 2002/09/02 23:41:16 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -399,7 +399,6 @@ Pg_connect(ClientData cData, Tcl_Interp *interp, int argc, char *argv[])
|
|||||||
int
|
int
|
||||||
Pg_disconnect(ClientData cData, Tcl_Interp *interp, int argc, char *argv[])
|
Pg_disconnect(ClientData cData, Tcl_Interp *interp, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
Pg_ConnectionId *connid;
|
|
||||||
PGconn *conn;
|
PGconn *conn;
|
||||||
Tcl_Channel conn_chan;
|
Tcl_Channel conn_chan;
|
||||||
|
|
||||||
@ -413,15 +412,14 @@ Pg_disconnect(ClientData cData, Tcl_Interp *interp, int argc, char *argv[])
|
|||||||
if (conn_chan == NULL)
|
if (conn_chan == NULL)
|
||||||
{
|
{
|
||||||
Tcl_ResetResult(interp);
|
Tcl_ResetResult(interp);
|
||||||
Tcl_AppendResult(interp, argv[1], " is not a valid connection\n", 0);
|
Tcl_AppendResult(interp, argv[1], " is not a valid connection", 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TCL_MAJOR_VERSION >= 8
|
/* Check that it is a PG connection and not something else */
|
||||||
conn = PgGetConnectionId(interp, argv[1], &connid);
|
conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId **) NULL);
|
||||||
if (connid->notifier_channel != NULL)
|
if (conn == (PGconn *) NULL)
|
||||||
Tcl_UnregisterChannel(interp, connid->notifier_channel);
|
return TCL_ERROR;
|
||||||
#endif
|
|
||||||
|
|
||||||
return Tcl_UnregisterChannel(interp, conn_chan);
|
return Tcl_UnregisterChannel(interp, conn_chan);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.33 2002/09/02 21:51:47 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.34 2002/09/02 23:41:17 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -144,6 +144,7 @@ static void
|
|||||||
PgWatchProc(ClientData instanceData, int mask)
|
PgWatchProc(ClientData instanceData, int mask)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
PgGetHandleProc(ClientData instanceData, int direction,
|
PgGetHandleProc(ClientData instanceData, int direction,
|
||||||
ClientData *handlePtr)
|
ClientData *handlePtr)
|
||||||
@ -193,7 +194,7 @@ PgSetConnectionId(Tcl_Interp *interp, PGconn *conn)
|
|||||||
|
|
||||||
#if TCL_MAJOR_VERSION >= 8
|
#if TCL_MAJOR_VERSION >= 8
|
||||||
connid->notifier_channel = Tcl_MakeTcpClientChannel((ClientData) PQsocket(conn));
|
connid->notifier_channel = Tcl_MakeTcpClientChannel((ClientData) PQsocket(conn));
|
||||||
Tcl_RegisterChannel(interp, connid->notifier_channel);
|
Tcl_RegisterChannel(NULL, connid->notifier_channel);
|
||||||
#else
|
#else
|
||||||
connid->notifier_socket = -1;
|
connid->notifier_socket = -1;
|
||||||
#endif
|
#endif
|
||||||
@ -227,6 +228,8 @@ PgGetConnectionId(Tcl_Interp *interp, char *id, Pg_ConnectionId ** connid_p)
|
|||||||
{
|
{
|
||||||
Tcl_ResetResult(interp);
|
Tcl_ResetResult(interp);
|
||||||
Tcl_AppendResult(interp, id, " is not a valid postgresql connection", 0);
|
Tcl_AppendResult(interp, id, " is not a valid postgresql connection", 0);
|
||||||
|
if (connid_p)
|
||||||
|
*connid_p = NULL;
|
||||||
return (PGconn *) NULL;
|
return (PGconn *) NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,6 +288,25 @@ PgDelConnectionId(DRIVER_DEL_PROTO)
|
|||||||
PQfinish(connid->conn);
|
PQfinish(connid->conn);
|
||||||
connid->conn = NULL;
|
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
|
* We must use Tcl_EventuallyFree because we don't want the connid
|
||||||
* struct to vanish instantly if Pg_Notify_EventProc is active for it.
|
* struct to vanish instantly if Pg_Notify_EventProc is active for it.
|
||||||
@ -782,8 +804,10 @@ PgStartNotifyEventSource(Pg_ConnectionId * connid)
|
|||||||
if (pqsock >= 0)
|
if (pqsock >= 0)
|
||||||
{
|
{
|
||||||
#if TCL_MAJOR_VERSION >= 8
|
#if TCL_MAJOR_VERSION >= 8
|
||||||
Tcl_CreateChannelHandler(connid->notifier_channel, TCL_READABLE,
|
Tcl_CreateChannelHandler(connid->notifier_channel,
|
||||||
Pg_Notify_FileHandler, (ClientData) connid);
|
TCL_READABLE,
|
||||||
|
Pg_Notify_FileHandler,
|
||||||
|
(ClientData) connid);
|
||||||
#else
|
#else
|
||||||
/* In Tcl 7.5 and 7.6, we need to gin up a Tcl_File. */
|
/* In Tcl 7.5 and 7.6, we need to gin up a Tcl_File. */
|
||||||
Tcl_File tclfile = Tcl_GetFile((ClientData) pqsock, TCL_UNIX_FD);
|
Tcl_File tclfile = Tcl_GetFile((ClientData) pqsock, TCL_UNIX_FD);
|
||||||
@ -805,7 +829,8 @@ PgStopNotifyEventSource(Pg_ConnectionId * connid, bool allevents)
|
|||||||
{
|
{
|
||||||
#if TCL_MAJOR_VERSION >= 8
|
#if TCL_MAJOR_VERSION >= 8
|
||||||
Tcl_DeleteChannelHandler(connid->notifier_channel,
|
Tcl_DeleteChannelHandler(connid->notifier_channel,
|
||||||
Pg_Notify_FileHandler, (ClientData) connid);
|
Pg_Notify_FileHandler,
|
||||||
|
(ClientData) connid);
|
||||||
#else
|
#else
|
||||||
/* In Tcl 7.5 and 7.6, we need to gin up a Tcl_File. */
|
/* In Tcl 7.5 and 7.6, we need to gin up a Tcl_File. */
|
||||||
Tcl_File tclfile = Tcl_GetFile((ClientData) connid->notifier_socket,
|
Tcl_File tclfile = Tcl_GetFile((ClientData) connid->notifier_socket,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user