summaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
authormax <max@tclers.tk>2011-06-01 15:30:28 (GMT)
committermax <max@tclers.tk>2011-06-01 15:30:28 (GMT)
commitb8ee85e7eb1b906ac79f4fae165c4e8cf0e9faf4 (patch)
treeab6e4523edee145664636f9e2d3b1885f53de685 /unix
parent2f67cb7c57ed82cb80c4e9a3905850869b9c63c4 (diff)
downloadtcl-b8ee85e7eb1b906ac79f4fae165c4e8cf0e9faf4.zip
tcl-b8ee85e7eb1b906ac79f4fae165c4e8cf0e9faf4.tar.gz
tcl-b8ee85e7eb1b906ac79f4fae165c4e8cf0e9faf4.tar.bz2
* Improve socket.test by checking the latency on the loopback address and use that for some of the tests instead of fixed "big enough" times.
* Improve correctness of [socket -async] in some error cases.
Diffstat (limited to 'unix')
-rw-r--r--unix/tclUnixSock.c66
1 files changed, 33 insertions, 33 deletions
diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c
index 823942a..981162d 100644
--- a/unix/tclUnixSock.c
+++ b/unix/tclUnixSock.c
@@ -885,10 +885,12 @@ CreateClientSocket(
Tcl_Interp *interp, /* For error reporting; can be NULL. */
TcpState *state)
{
+ socklen_t optlen;
+ int in_coro = (state->addr != NULL);
int status, connected = 0;
int async = state->flags & TCP_ASYNC_CONNECT;
- if (state->addr != NULL) {
+ if (in_coro) {
goto coro_continue;
}
@@ -966,53 +968,51 @@ CreateClientSocket(
Tcl_CreateFileHandler(state->fds->fd, TCL_WRITABLE,
TcpAsyncCallback, state);
return TCL_OK;
+
coro_continue:
- do {
- socklen_t optlen = sizeof(int);
- Tcl_DeleteFileHandler(state->fds->fd);
- getsockopt(state->fds->fd, SOL_SOCKET, SO_ERROR,
- (char *)&status, &optlen);
- state->status = status;
- } while (0);
+ Tcl_DeleteFileHandler(state->fds->fd);
+ /*
+ * Read the error state from the socket, to see if the async
+ * connection has succeeded or failed and store the status in
+ * the socket state for later retrieval by [fconfigure -error]
+ */
+ optlen = sizeof(int);
+ getsockopt(state->fds->fd, SOL_SOCKET, SO_ERROR,
+ (char *)&status, &optlen);
+ state->status = status;
}
if (status == 0) {
- connected = 1;
- break;
+ goto out;
}
}
- if (connected) {
- break;
- }
}
- if (async) {
- /*
- * Restore blocking mode.
- */
- status = TclUnixSetBlockingMode(state->fds->fd, TCL_MODE_BLOCKING);
- }
+out:
freeaddrinfo(state->addrlist);
freeaddrinfo(state->myaddrlist);
if (async) {
CLEAR_BITS(state->flags, TCP_ASYNC_CONNECT);
- if (state->filehandlers != 0) {
- TcpWatchProc(state, state->filehandlers);
- }
- return TCL_OK;
+ TcpWatchProc(state, state->filehandlers);
+ TclUnixSetBlockingMode(state->fds->fd, TCL_MODE_BLOCKING);
}
+
if (status < 0) {
- if (interp != NULL) {
- 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;
+ if (in_coro) {
+ Tcl_NotifyChannel(state->fds->fd, TCL_WRITABLE);
+ } else {
+ if (interp != NULL) {
+ 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;
+ }
}
return TCL_OK;
}