mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -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