summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixSock.c
diff options
context:
space:
mode:
authormax <max@tclers.tk>2014-04-04 10:02:47 (GMT)
committermax <max@tclers.tk>2014-04-04 10:02:47 (GMT)
commit053685ad2952fe7a83cf63ff28ec273862c903b3 (patch)
treee28f08521e12f9fde833f2d4762ff83db2b77f9b /unix/tclUnixSock.c
parent8978760b1a95d061dff0d9c3f0c8a997aa56998d (diff)
downloadtcl-053685ad2952fe7a83cf63ff28ec273862c903b3.zip
tcl-053685ad2952fe7a83cf63ff28ec273862c903b3.tar.gz
tcl-053685ad2952fe7a83cf63ff28ec273862c903b3.tar.bz2
* Rework WaitForConnect() to fix synchronous completion of asynchronous connections.
* Let TcpInputProc() and TcpOutputProc() fail before calling any I/O syscalls when an asynchronous connection has failed. * Adjust the tests accordingly.
Diffstat (limited to 'unix/tclUnixSock.c')
-rw-r--r--unix/tclUnixSock.c54
1 files changed, 24 insertions, 30 deletions
diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c
index 466b231..d4b7b62 100644
--- a/unix/tclUnixSock.c
+++ b/unix/tclUnixSock.c
@@ -128,8 +128,7 @@ static int TcpInputProc(ClientData instanceData, char *buf,
static int TcpOutputProc(ClientData instanceData,
const char *buf, int toWrite, int *errorCode);
static void TcpWatchProc(ClientData instanceData, int mask);
-static int WaitForConnect(TcpState *statePtr, int *errorCodePtr,
- int noblock);
+static int WaitForConnect(TcpState *statePtr, int noblock);
/*
* This structure describes the channel type structure for TCP socket
@@ -399,41 +398,33 @@ TcpBlockModeProc(
static int
WaitForConnect(
TcpState *statePtr, /* State of the socket. */
- int *errorCodePtr, /* Where to store errors? */
int noblock) /* Don't wait, even for sockets in blocking mode */
{
- int timeOut; /* How long to wait. */
- int state; /* Of calling TclWaitForFile. */
-
/*
* If an asynchronous connect is in progress, attempt to wait for it to
* complete before reading.
*/
if (statePtr->flags & TCP_ASYNC_CONNECT) {
- if (noblock || statePtr->flags & TCP_ASYNC_SOCKET) {
- timeOut = 0;
+ if (noblock || (statePtr->flags & TCP_ASYNC_SOCKET)) {
+ if (TclUnixWaitForFile(statePtr->fds.fd,
+ TCL_WRITABLE | TCL_EXCEPTION, 0) != 0) {
+ CreateClientSocket(NULL, statePtr);
+ }
} else {
- timeOut = -1;
- CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
- }
- errno = 0;
- state = TclUnixWaitForFile(statePtr->fds.fd,
- TCL_WRITABLE | TCL_EXCEPTION, timeOut);
- if (state != 0) {
- CreateClientSocket(NULL, statePtr);
- }
- if (statePtr->flags & TCP_ASYNC_CONNECT) {
- /* We are still in progress, so ignore the result of the last
- * attempt */
- *errorCodePtr = errno = EWOULDBLOCK;
- return -1;
+ while (statePtr->flags & TCP_ASYNC_CONNECT) {
+ if (TclUnixWaitForFile(statePtr->fds.fd,
+ TCL_WRITABLE | TCL_EXCEPTION, -1) != 0) {
+ CreateClientSocket(NULL, statePtr);
+ }
+ }
}
- if (state & TCL_EXCEPTION) {
- return -1;
- }
}
- return 0;
+ if (statePtr->error != 0) {
+ return -1;
+ } else {
+ return 0;
+ }
}
/*
@@ -471,7 +462,9 @@ TcpInputProc(
int bytesRead;
*errorCodePtr = 0;
- if (WaitForConnect(statePtr, errorCodePtr, 0) != 0) {
+ if (WaitForConnect(statePtr, 0) != 0) {
+ *errorCodePtr = statePtr->error;
+ statePtr->error = 0;
return -1;
}
bytesRead = recv(statePtr->fds.fd, buf, (size_t) bufSize, 0);
@@ -521,7 +514,9 @@ TcpOutputProc(
int written;
*errorCodePtr = 0;
- if (WaitForConnect(statePtr, errorCodePtr, 0) != 0) {
+ if (WaitForConnect(statePtr, 0) != 0) {
+ *errorCodePtr = statePtr->error;
+ statePtr->error = 0;
return -1;
}
written = send(statePtr->fds.fd, buf, (size_t) toWrite, 0);
@@ -748,9 +743,8 @@ TcpGetOptionProc(
{
TcpState *statePtr = instanceData;
size_t len = 0;
- int errorCode;
- WaitForConnect(statePtr, &errorCode, 1);
+ WaitForConnect(statePtr, 1);
if (optionName != NULL) {
len = strlen(optionName);