diff options
author | max <max@tclers.tk> | 2011-06-07 14:31:59 (GMT) |
---|---|---|
committer | max <max@tclers.tk> | 2011-06-07 14:31:59 (GMT) |
commit | 938cb914fee8405b397ae0823e16444bc9eb7c0c (patch) | |
tree | a368a1979b1ea5a20da1082b04a726a11f927b33 /unix | |
parent | cd37602cf4924672b4219fdf144d76e2cf773947 (diff) | |
download | tcl-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.c | 51 |
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; } |