Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Async connect terminates: fire fileevent by setting readyEvent, propage commit fail message to [fconfigure -error] |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | bug-13d3af3ad5 |
Files: | files | file ages | folders |
SHA1: |
711c272f369d86d95493230c1999184a |
User & Date: | oehhar 2014-03-14 09:12:13 |
Context
2014-03-14
| ||
14:26 |
| |
10:59 | Remove writable shortcut and errorneous workaround to get [connect -async] fail error to [fconfigure... Closed-Leaf check-in: aa6c8b17e1 user: oehhar tags: bug-13d3af3ad5-fork | |
09:12 | Async connect terminates: fire fileevent by setting readyEvent, propage commit fail message to [fcon... check-in: 711c272f36 user: oehhar tags: bug-13d3af3ad5 | |
2014-03-11
| ||
17:34 |
| |
Changes
Changes to win/tclWinSock.c.
︙ | ︙ | |||
166 167 168 169 170 171 172 | ClientData acceptProcData; /* The data for the accept proc. */ 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 status; /* Cache status of async socket. */ int cachedBlocking; /* Cache blocking mode of async socket. */ | | > | 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | ClientData acceptProcData; /* The data for the accept proc. */ 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 status; /* Cache status of async socket. */ int cachedBlocking; /* Cache blocking mode of async socket. */ int lastError; /* Error code from notifier thread. */ int connectError; /* Error code from failed async connect. */ struct SocketInfo *nextPtr; /* The next socket on the per-thread socket * list. */ }; /* * The following structure is what is added to the Tcl event queue when a * socket event occurs. |
︙ | ︙ | |||
239 240 241 242 243 244 245 | static void InitSockets(void); static SocketInfo * NewSocketInfo(SOCKET socket); static void SocketExitHandler(ClientData clientData); static LRESULT CALLBACK SocketProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static int SocketsEnabled(void); static void TcpAccept(TcpFdList *fds, SOCKET newSocket, address addr); | | > | 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | static void InitSockets(void); static SocketInfo * NewSocketInfo(SOCKET socket); static void SocketExitHandler(ClientData clientData); static LRESULT CALLBACK SocketProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static int SocketsEnabled(void); static void TcpAccept(TcpFdList *fds, SOCKET newSocket, address addr); static int WaitForConnect(SocketInfo *infoPtr, int *errorCodePtr, int terminate_connect); static int WaitForSocketEvent(SocketInfo *infoPtr, int events, int *errorCodePtr); static int FindFDInList(SocketInfo *infoPtr, SOCKET socket); static DWORD WINAPI SocketThread(LPVOID arg); static void TcpThreadActionProc(ClientData instanceData, int action); |
︙ | ︙ | |||
774 775 776 777 778 779 780 781 | infoPtr->flags &= ~SOCKET_PENDING; /* Continue async connect if pending and ready */ if ( infoPtr->readyEvents & FD_CONNECT ) { infoPtr->readyEvents &= ~(FD_CONNECT); DEBUG("FD_CONNECT"); if ( infoPtr->flags & SOCKET_REENTER_PENDING ) { SetEvent(tsdPtr->socketListLock); | > > | < > > > | 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 | infoPtr->flags &= ~SOCKET_PENDING; /* Continue async connect if pending and ready */ if ( infoPtr->readyEvents & FD_CONNECT ) { infoPtr->readyEvents &= ~(FD_CONNECT); DEBUG("FD_CONNECT"); if ( infoPtr->flags & SOCKET_REENTER_PENDING ) { /* free list lock */ SetEvent(tsdPtr->socketListLock); /* Do one connect step */ if (TCL_OK != CreateClientSocket(NULL, infoPtr) ) { /* On final fail save error for fconfigure -error */ infoPtr->connectError = Tcl_GetErrno(); } } } /* * Handle connection requests directly. */ if (infoPtr->readyEvents & FD_ACCEPT) { |
︙ | ︙ | |||
1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 | if (Tcl_GetErrno() == 0) { goto out; } } } out: DEBUG("connected or finally failed"); /* Clear async flag (not really necessary, not used any more) */ infoPtr->flags &= ~(SOCKET_ASYNC_CONNECT); | > > > < < < < < | | | | < < | < < > > > > | | | | | | | | | | | < < | | > > > > > > > > > | > > > > | > > > > > > > > > > > > > > > | | > > | > | > > | > | 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 | if (Tcl_GetErrno() == 0) { goto out; } } } out: /* * Socket connected or connection failed */ DEBUG("connected or finally failed"); /* Clear async flag (not really necessary, not used any more) */ infoPtr->flags &= ~(SOCKET_ASYNC_CONNECT); /* * Final connect failure */ if ( Tcl_GetErrno() == 0 ) { /* * Succesfully connected */ /* * Set up the select mask for read/write events. */ DEBUG("selectEvents = FD_READ | FD_WRITE | FD_CLOSE"); infoPtr->selectEvents = FD_READ | FD_WRITE | FD_CLOSE; /* * Register for interest in events in the select mask. Note that this * automatically places the socket into non-blocking mode. */ SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT, (LPARAM) infoPtr); } else { /* * Connect failed */ DEBUG("ERRNO"); /* * For async connect schedule a writable event to report the fail. */ if (async_callback) { /* * Set up the select mask for read/write events. */ DEBUG("selectEvents = FD_WRITE for fail writable"); infoPtr->selectEvents = FD_WRITE; /* get infoPtr lock */ WaitForSingleObject(tsdPtr->socketListLock, INFINITE); /* Clear eventual connect flag */ infoPtr->readyEvents |= FD_WRITE; /* Free list lock */ SetEvent(tsdPtr->socketListLock); } /* * Error message on syncroneous connect */ if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open socket: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * WaitForConnect -- * * Process an asyncroneous connect by other commands (gets... ). * Do one connect step if pending as if the event loop would run. * * Blocking commands may call in with terminate_connect to terminate * the syncroneous connect syncroneously. * * This routine should only be called if flag SOCKET_REENTER_PENDING * is set. * * Results: * Returns 1 on success or 0 on failure, with a possix error code in * errorCodePtr. * If the connect is not terminated, errorCode is set to EWOULDBLOCK * and 0 is returned. * * Side effects: * Processes socket events off the system queue. * May process asynchroneous connect. * *---------------------------------------------------------------------- */ static int WaitForConnect( SocketInfo *infoPtr, /* Information about this socket. */ int *errorCodePtr, /* Where to store errors? */ int terminate_connect) /* Should the connect be terminated? */ { int result; int oldMode; ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey); /* * Be sure to disable event servicing so we are truly modal. |
︙ | ︙ | |||
1479 1480 1481 1482 1483 1484 1485 | /* Consume the connect event */ infoPtr->readyEvents &= ~(FD_CONNECT); /* * For blocking sockets disable async connect * as we continue now synchoneously */ | | | 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 | /* Consume the connect event */ infoPtr->readyEvents &= ~(FD_CONNECT); /* * For blocking sockets disable async connect * as we continue now synchoneously */ if ( terminate_connect ) { infoPtr->flags &= ~(SOCKET_ASYNC_CONNECT); } /* Free list lock */ SetEvent(tsdPtr->socketListLock); /* continue connect */ |
︙ | ︙ | |||
1512 1513 1514 1515 1516 1517 1518 | /* Free list lock */ SetEvent(tsdPtr->socketListLock); /* * A non blocking socket waiting for an asyncronous connect * returns directly an error */ | | | 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 | /* Free list lock */ SetEvent(tsdPtr->socketListLock); /* * A non blocking socket waiting for an asyncronous connect * returns directly an error */ if ( ! terminate_connect ) { *errorCodePtr = EWOULDBLOCK; return 0; } /* * Wait until something happens. */ |
︙ | ︙ | |||
2064 2065 2066 2067 2068 2069 2070 | */ if (infoPtr->flags & SOCKET_EOF) { return 0; } /* | | > > | > | 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 | */ if (infoPtr->flags & SOCKET_EOF) { return 0; } /* * Check if there is an async connect running. * For blocking sockets terminate connect, otherwise do one step. * For a non blocking socket return EWOULDBLOCK if connect not terminated */ if ( (infoPtr->flags & SOCKET_REENTER_PENDING) && !WaitForConnect(infoPtr, errorCodePtr, ! ( infoPtr->flags & TCP_ASYNC_SOCKET ))) { return -1; } /* * No EOF, and it is connected, so try to read more from the socket. Note * that we clear the FD_READ bit because read events are level triggered * so a new event will be generated if there is still data available to be |
︙ | ︙ | |||
2192 2193 2194 2195 2196 2197 2198 | if (!SocketsEnabled()) { *errorCodePtr = EFAULT; return -1; } /* | | > > | > | 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 | if (!SocketsEnabled()) { *errorCodePtr = EFAULT; return -1; } /* * Check if there is an async connect running. * For blocking sockets terminate connect, otherwise do one step. * For a non blocking socket return EWOULDBLOCK if connect not terminated */ if ( (infoPtr->flags & SOCKET_REENTER_PENDING) && !WaitForConnect(infoPtr, errorCodePtr, ! ( infoPtr->flags & TCP_ASYNC_SOCKET ))) { return -1; } while (1) { SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) UNSELECT, (LPARAM) infoPtr); |
︙ | ︙ | |||
2414 2415 2416 2417 2418 2419 2420 | sock = infoPtr->sockets->fd; if (optionName != NULL) { len = strlen(optionName); } if ((len > 1) && (optionName[1] == 'e') && (strncmp(optionName, "-error", len) == 0)) { | | > > | | > | > | | > > > > > > > > > > > | > < < | | | | > > | 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 | sock = infoPtr->sockets->fd; if (optionName != NULL) { len = strlen(optionName); } if ((len > 1) && (optionName[1] == 'e') && (strncmp(optionName, "-error", len) == 0)) { if ( (infoPtr->flags & SOCKET_REENTER_PENDING) ) { /* * Asyncroneous connect is running. * Process it one step without blocking. * Return its error or nothing if connect not * terminated. */ int errorCode; if (!WaitForConnect(infoPtr, &errorCode, 0) && errorCode != EWOULDBLOCK) { /* connect terminated with error */ Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(errorCode), -1); } } else if (infoPtr->connectError != 0) { /* * An async connect error was not jet reported. */ Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(infoPtr->connectError), -1); infoPtr->connectError = 0; } else { int optlen; int ret; DWORD err; optlen = sizeof(int); ret = TclWinGetSockOpt(sock, SOL_SOCKET, SO_ERROR, (char *)&err, &optlen); if (ret == SOCKET_ERROR) { err = WSAGetLastError(); if (err) { TclWinConvertError(err); Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(Tcl_GetErrno()), -1); } } } return TCL_OK; } if (interp != NULL && Tcl_GetVar(interp, SUPPRESS_RDNS_VAR, 0) != NULL) { reverseDNS = NI_NUMERICHOST; } |
︙ | ︙ | |||
2967 2968 2969 2970 2971 2972 2973 | FindFDInList( SocketInfo *infoPtr, SOCKET socket) { TcpFdList *fds; for (fds = infoPtr->sockets; fds != NULL; fds = fds->next) { #ifdef DEBUGGING | | | 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 | FindFDInList( SocketInfo *infoPtr, SOCKET socket) { TcpFdList *fds; for (fds = infoPtr->sockets; fds != NULL; fds = fds->next) { #ifdef DEBUGGING fprintf(stderr,"socket = %d, fd=%d\n",socket,fds); #endif if (fds->fd == socket) { return 1; } } return 0; } |
︙ | ︙ |