summaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
authormax <max@tclers.tk>2011-06-07 14:31:59 (GMT)
committermax <max@tclers.tk>2011-06-07 14:31:59 (GMT)
commit938cb914fee8405b397ae0823e16444bc9eb7c0c (patch)
treea368a1979b1ea5a20da1082b04a726a11f927b33 /unix
parentcd37602cf4924672b4219fdf144d76e2cf773947 (diff)
downloadtcl-938cb914fee8405b397ae0823e16444bc9eb7c0c.zip
tcl-938cb914fee8405b397ae0823e16444bc9eb7c0c.tar.gz
tcl-938cb914fee8405b397ae0823e16444bc9eb7c0c.tar.bz2
Fix bug#3084338, a memleak when a [socket -async] was closed before the connection had succeeded or failed.
Diffstat (limited to 'unix')
-rw-r--r--unix/tclUnixSock.c51
1 files changed, 22 insertions, 29 deletions
diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c
index 0d6b1d0..39fb375 100644
--- a/unix/tclUnixSock.c
+++ b/unix/tclUnixSock.c
@@ -53,27 +53,21 @@ struct TcpState {
TcpFdList *fds; /* The file descriptors of the sockets. */
int flags; /* ORed combination of the bitfields defined
* below. */
- union {
- struct {
- /* Only needed for server sockets */
- Tcl_TcpAcceptProc *acceptProc;
- /* Proc to call on accept. */
- ClientData acceptProcData;
- /* The data for the accept proc. */
- };
- struct {
- /*
- * Only needed for client sockets
- */
- struct addrinfo *addrlist; /* addresses to connect to */
- struct addrinfo *addr; /* iterator over addrlist */
- struct addrinfo *myaddrlist; /* local address */
- struct addrinfo *myaddr; /* iterator over myaddrlist */
- int filehandlers; /* Caches FileHandlers that get set up while
- * an async socket is not yet connected */
- int status; /* Cache status of async socket */
- };
- };
+ /*
+ * Only needed for server sockets
+ */
+ Tcl_TcpAcceptProc *acceptProc; /* Proc to call on accept. */
+ ClientData acceptProcData; /* The data for the accept proc. */
+ /*
+ * Only needed for client sockets
+ */
+ struct addrinfo *addrlist; /* addresses to connect to */
+ struct addrinfo *addr; /* iterator over addrlist */
+ struct addrinfo *myaddrlist; /* local address */
+ struct addrinfo *myaddr; /* iterator over myaddrlist */
+ int filehandlers; /* Caches FileHandlers that get set up while
+ * an async socket is not yet connected */
+ int status; /* Cache status of async socket */
};
/*
@@ -551,6 +545,12 @@ TcpCloseProc(
}
ckfree(fds);
}
+ if (statePtr->addrlist != NULL) {
+ freeaddrinfo(statePtr->addrlist);
+ }
+ if (statePtr->myaddrlist != NULL) {
+ freeaddrinfo(statePtr->myaddrlist);
+ }
ckfree(statePtr);
return errorCode;
}
@@ -993,9 +993,6 @@ CreateClientSocket(
out:
- freeaddrinfo(state->addrlist);
- freeaddrinfo(state->myaddrlist);
-
if (async) {
CLEAR_BITS(state->flags, TCP_ASYNC_CONNECT);
TcpWatchProc(state, state->filehandlers);
@@ -1010,11 +1007,6 @@ out:
Tcl_AppendResult(interp, "couldn't open socket: ",
Tcl_PosixError(interp), NULL);
}
- if (state->fds->fd != -1) {
- close(state->fds->fd);
- }
- ckfree(state->fds);
- ckfree(state);
return TCL_ERROR;
}
}
@@ -1088,6 +1080,7 @@ Tcl_OpenTcpClient(
* Create a new client socket and wrap it in a channel.
*/
if (CreateClientSocket(interp, state) != TCL_OK) {
+ TcpCloseProc(state, NULL);
return NULL;
}