Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Replaced option "-unsupported1" by test command "testsocket debugflags" (thanks Donal, Donald). |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | robust-async-connect-tests |
Files: | files | file ages | folders |
SHA1: |
33737f615baaff2041d55aea17e6029a |
User & Date: | oehhar 2014-07-17 09:53:36 |
Original Comment: | Replaced option "-unsupported1" by test command "testsocket debuglags" (thanks Donal, Donald). |
Context
2014-07-18
| ||
07:32 | merge trunk check-in: b094ff21be user: jan.nijtmans tags: robust-async-connect-tests | |
2014-07-17
| ||
12:49 | Minor code improvement: combine "flags" and "testFlags" struct members to a single one. check-in: f1e67b2730 user: jan.nijtmans tags: mistake | |
09:53 | Replaced option "-unsupported1" by test command "testsocket debugflags" (thanks Donal, Donald). check-in: 33737f615b user: oehhar tags: robust-async-connect-tests | |
2014-06-05
| ||
19:09 | Robust async connect tests by temporarely switching off auto continuation. Ticket [13d3af3ad5] check-in: 0c5005721e user: oehhar tags: robust-async-connect-tests | |
Changes
Changes to generic/tclTest.c.
︙ | ︙ | |||
70 71 72 73 74 75 76 77 78 79 80 81 82 83 | int id; /* Identifier for this handler. */ Tcl_AsyncHandler handler; /* Tcl's token for the handler. */ char *command; /* Command to invoke when the handler is * invoked. */ struct TestAsyncHandler *nextPtr; /* Next is list of handlers. */ } TestAsyncHandler; TCL_DECLARE_MUTEX(asyncTestMutex) static TestAsyncHandler *firstHandler = NULL; /* * The dynamic string below is used by the "testdstring" command to test the | > > > > > > > > > > > > | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | int id; /* Identifier for this handler. */ Tcl_AsyncHandler handler; /* Tcl's token for the handler. */ char *command; /* Command to invoke when the handler is * invoked. */ struct TestAsyncHandler *nextPtr; /* Next is list of handlers. */ } TestAsyncHandler; /* * Start of the socket driver state structure to acces field testFlags */ typedef struct TcpState TcpState; struct TcpState { Tcl_Channel channel; /* Channel associated with this socket. */ int testFlags; /* bit field for tests. Is set by testsocket * test procedure */ }; TCL_DECLARE_MUTEX(asyncTestMutex) static TestAsyncHandler *firstHandler = NULL; /* * The dynamic string below is used by the "testdstring" command to test the |
︙ | ︙ | |||
357 358 359 360 361 362 363 364 365 366 367 368 369 370 | int objc, Tcl_Obj *const objv[]); static int TestGetIndexFromObjStructObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestChannelCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); static int TestChannelEventCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); static int TestFilesystemObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestSimpleFilesystemObjCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); | > > | 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | int objc, Tcl_Obj *const objv[]); static int TestGetIndexFromObjStructObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestChannelCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); static int TestChannelEventCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); static int TestSocketCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); static int TestFilesystemObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestSimpleFilesystemObjCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); |
︙ | ︙ | |||
661 662 663 664 665 666 667 668 669 670 671 672 673 674 | Tcl_CreateCommand(interp, "testseterrorcode", TestseterrorcodeCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testsetobjerrorcode", TestsetobjerrorcodeCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testnumutfchars", TestNumUtfCharsCmd, NULL, NULL); Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd, NULL, NULL); Tcl_CreateCommand(interp, "teststaticpkg", TeststaticpkgCmd, NULL, NULL); Tcl_CreateCommand(interp, "testtranslatefilename", TesttranslatefilenameCmd, NULL, NULL); Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, NULL, NULL); #ifndef TCL_NO_DEPRECATED | > > | 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 | Tcl_CreateCommand(interp, "testseterrorcode", TestseterrorcodeCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testsetobjerrorcode", TestsetobjerrorcodeCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testnumutfchars", TestNumUtfCharsCmd, NULL, NULL); Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd, NULL, NULL); Tcl_CreateCommand(interp, "testsocket", TestSocketCmd, NULL, NULL); Tcl_CreateCommand(interp, "teststaticpkg", TeststaticpkgCmd, NULL, NULL); Tcl_CreateCommand(interp, "testtranslatefilename", TesttranslatefilenameCmd, NULL, NULL); Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, NULL, NULL); #ifndef TCL_NO_DEPRECATED |
︙ | ︙ | |||
5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 | TclChannelEventScriptInvoker, (ClientData) esPtr); return TCL_OK; } Tcl_AppendResult(interp, "bad command ", cmd, ", must be one of " "add, delete, list, set, or removeall", NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TestWrongNumArgsObjCmd -- * * Test the Tcl_WrongNumArgs function. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 | TclChannelEventScriptInvoker, (ClientData) esPtr); return TCL_OK; } Tcl_AppendResult(interp, "bad command ", cmd, ", must be one of " "add, delete, list, set, or removeall", NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TestSocketCmd -- * * Implements the Tcl "testsocket" debugging command and its * subcommands. This is part of the testing environment. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestSocketCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Interpreter for result. */ int argc, /* Count of additional args. */ const char **argv) /* Additional arg strings. */ { const char *cmdName; /* Sub command. */ size_t len; /* Length of subcommand string. */ if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " subcommand ?additional args..?\"", NULL); return TCL_ERROR; } cmdName = argv[1]; len = strlen(cmdName); if ((cmdName[0] == 't') && (strncmp(cmdName, "testflags", len) == 0)) { Tcl_Channel hChannel; int modePtr; TcpState *statePtr; /* Set test value in the socket driver */ /* Check for argument "channel name" */ if (argc < 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " testflags channel flags\"", NULL); return TCL_ERROR; } hChannel = Tcl_GetChannel(interp, argv[2], &modePtr); if ( NULL == hChannel ) { Tcl_AppendResult(interp, "unknown channel:", argv[2], NULL); return TCL_ERROR; } statePtr = (TcpState *)Tcl_GetChannelInstanceData(hChannel); if ( NULL == statePtr) { Tcl_AppendResult(interp, "No channel instance data:", argv[2], NULL); return TCL_ERROR; } statePtr->testFlags = atoi(argv[3]); return TCL_OK; } Tcl_AppendResult(interp, "bad option \"", cmdName, "\": should be " "testflags", NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TestWrongNumArgsObjCmd -- * * Test the Tcl_WrongNumArgs function. |
︙ | ︙ |
Changes to tests/socket.test.
︙ | ︙ | |||
68 69 70 71 72 73 74 | testConstraint exec [llength [info commands exec]] # Produce a random port number in the Dynamic/Private range # from 49152 through 65535. proc randport {} { expr {int(rand()*16383+49152)} } | | | | | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | testConstraint exec [llength [info commands exec]] # Produce a random port number in the Dynamic/Private range # from 49152 through 65535. proc randport {} { expr {int(rand()*16383+49152)} } # Check if testsocket testflags is available testConstraint testsocket_testflags [expr {![catch { set h [socket -async localhost [randport]] testsocket testflags $h 0 close $h }]}] # Test the latency of tcp connections over the loopback interface. Some OSes # (e.g. NetBSD) seem to use the Nagle algorithm and delayed ACKs, so it takes # up to 200ms for a packet sent to localhost to arrive. We're measuring this |
︙ | ︙ | |||
2166 2167 2168 2169 2170 2171 2172 | vwait x close $sock } -cleanup { catch {close $sock} unset x } -result {socket is not connected} -returnCodes 1 test socket-14.11.1 {pending [socket -async] and nonblocking [puts], no listener, flush} \ | | > > > | | | 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 | vwait x close $sock } -cleanup { catch {close $sock} unset x } -result {socket is not connected} -returnCodes 1 test socket-14.11.1 {pending [socket -async] and nonblocking [puts], no listener, flush} \ -constraints {socket testsocket_testflags} \ -body { set sock [socket -async localhost [randport]] # Set the socket in async test mode. # The async connect will not be continued on the following fconfigure # and puts/flush. Thus, the connect will fail after them. testsocket testflags $sock 1 fconfigure $sock -blocking 0 puts $sock ok flush $sock testsocket testflags $sock 0 fileevent $sock writable {set x 1} vwait x close $sock } -cleanup { catch {close $sock} catch {unset x} } -result {socket is not connected} -returnCodes 1 |
︙ | ︙ |
Changes to unix/tclUnixSock.c.
︙ | ︙ | |||
48 49 50 51 52 53 54 55 56 57 58 59 60 61 | TcpState *statePtr; int fd; struct TcpFdList *next; } TcpFdList; struct TcpState { Tcl_Channel channel; /* Channel associated with this file. */ TcpFdList fds; /* The file descriptors of the sockets. */ int flags; /* ORed combination of the bitfields defined * below. */ /* * Only needed for server sockets */ | > > | 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | TcpState *statePtr; int fd; struct TcpFdList *next; } TcpFdList; struct TcpState { Tcl_Channel channel; /* Channel associated with this file. */ int testFlags; /* bit field for tests. Is set by testsocket * test procedure */ TcpFdList fds; /* The file descriptors of the sockets. */ int flags; /* ORed combination of the bitfields defined * below. */ /* * Only needed for server sockets */ |
︙ | ︙ | |||
85 86 87 88 89 90 91 | #define TCP_NONBLOCKING (1<<0) /* Socket with non-blocking I/O */ #define TCP_ASYNC_CONNECT (1<<1) /* Async connect in progress. */ #define TCP_ASYNC_PENDING (1<<4) /* TcpConnect was called to * process an async connect. This * flag indicates that reentry is * still pending */ #define TCP_ASYNC_FAILED (1<<5) /* An async connect finally failed */ | > > > > > > | | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | #define TCP_NONBLOCKING (1<<0) /* Socket with non-blocking I/O */ #define TCP_ASYNC_CONNECT (1<<1) /* Async connect in progress. */ #define TCP_ASYNC_PENDING (1<<4) /* TcpConnect was called to * process an async connect. This * flag indicates that reentry is * still pending */ #define TCP_ASYNC_FAILED (1<<5) /* An async connect finally failed */ /* * These bits may be ORed together into the "testFlags" field of a TcpState * structure. */ #define TCP_ASYNC_TEST_MODE (1<<0) /* Async testing activated * Do not automatically continue connection * process */ /* * The following defines the maximum length of the listen queue. This is the * number of outstanding yet-to-be-serviced requests for a connection on a * server socket, more than this number of outstanding requests and the |
︙ | ︙ | |||
124 125 126 127 128 129 130 | static int TcpBlockModeProc(ClientData data, int mode); static int TcpCloseProc(ClientData instanceData, Tcl_Interp *interp); static int TcpClose2Proc(ClientData instanceData, Tcl_Interp *interp, int flags); static int TcpGetHandleProc(ClientData instanceData, int direction, ClientData *handlePtr); | < < < | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | static int TcpBlockModeProc(ClientData data, int mode); static int TcpCloseProc(ClientData instanceData, Tcl_Interp *interp); static int TcpClose2Proc(ClientData instanceData, Tcl_Interp *interp, int flags); static int TcpGetHandleProc(ClientData instanceData, int direction, ClientData *handlePtr); static int TcpGetOptionProc(ClientData instanceData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); static int TcpInputProc(ClientData instanceData, char *buf, int toRead, int *errorCode); static int TcpOutputProc(ClientData instanceData, const char *buf, int toWrite, int *errorCode); |
︙ | ︙ | |||
149 150 151 152 153 154 155 | static const Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ TcpCloseProc, /* Close proc. */ TcpInputProc, /* Input proc. */ TcpOutputProc, /* Output proc. */ NULL, /* Seek proc. */ | | | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | static const Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ TcpCloseProc, /* Close proc. */ TcpInputProc, /* Input proc. */ TcpOutputProc, /* Output proc. */ NULL, /* Seek proc. */ NULL, /* Set option proc. */ TcpGetOptionProc, /* Get option proc. */ TcpWatchProc, /* Initialize notifier. */ TcpGetHandleProc, /* Get OS handles out of channel. */ TcpClose2Proc, /* Close2 proc. */ TcpBlockModeProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ |
︙ | ︙ | |||
449 450 451 452 453 454 455 | /* * In socket test mode do not continue with the connect * Exceptions are: * - Call by recv/send and blocking socket * (errorCodePtr != NULL && ! flags & TCP_NONBLOCKING) */ | | | < | < | 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 | /* * In socket test mode do not continue with the connect * Exceptions are: * - Call by recv/send and blocking socket * (errorCodePtr != NULL && ! flags & TCP_NONBLOCKING) */ if ( (statePtr->testFlags & TCP_ASYNC_TEST_MODE) && ! (errorCodePtr != NULL && ! (statePtr->flags & TCP_NONBLOCKING))) { *errorCodePtr = EWOULDBLOCK; return -1; } if (errorCodePtr == NULL || (statePtr->flags & TCP_NONBLOCKING)) { timeout = 0; } else { timeout = -1; |
︙ | ︙ | |||
761 762 763 764 765 766 767 | Tcl_DStringAppendElement(dsPtr, host); } else { /* Reverse mappong failed - use the numeric rep once more */ Tcl_DStringAppendElement(dsPtr, nhost); } Tcl_DStringAppendElement(dsPtr, nport); } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 764 765 766 767 768 769 770 771 772 773 774 775 776 777 | Tcl_DStringAppendElement(dsPtr, host); } else { /* Reverse mappong failed - use the numeric rep once more */ Tcl_DStringAppendElement(dsPtr, nhost); } Tcl_DStringAppendElement(dsPtr, nport); } /* *---------------------------------------------------------------------- * * TcpGetOptionProc -- * * Computes an option value for a TCP socket based channel, or a list of |
︙ | ︙ |
Changes to win/tclWinSock.c.
︙ | ︙ | |||
129 130 131 132 133 134 135 136 137 138 139 140 141 142 | TcpState *statePtr; SOCKET fd; struct TcpFdList *next; } TcpFdList; struct TcpState { Tcl_Channel channel; /* Channel associated with this socket. */ struct TcpFdList *sockets; /* Windows SOCKET handle. */ int flags; /* Bit field comprised of the flags described * below. */ int watchEvents; /* OR'ed combination of FD_READ, FD_WRITE, * FD_CLOSE, FD_ACCEPT and FD_CONNECT that * indicate which events are interesting. */ volatile int readyEvents; /* OR'ed combination of FD_READ, FD_WRITE, | > > | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | TcpState *statePtr; SOCKET fd; struct TcpFdList *next; } TcpFdList; struct TcpState { Tcl_Channel channel; /* Channel associated with this socket. */ int testFlags; /* bit field for tests. Is set by testsocket * test procedure */ struct TcpFdList *sockets; /* Windows SOCKET handle. */ int flags; /* Bit field comprised of the flags described * below. */ int watchEvents; /* OR'ed combination of FD_READ, FD_WRITE, * FD_CLOSE, FD_ACCEPT and FD_CONNECT that * indicate which events are interesting. */ volatile int readyEvents; /* OR'ed combination of FD_READ, FD_WRITE, |
︙ | ︙ | |||
187 188 189 190 191 192 193 | #define SOCKET_PENDING (1<<3) /* A message has been sent for this * socket */ #define TCP_ASYNC_PENDING (1<<4) /* TcpConnect was called to * process an async connect. This * flag indicates that reentry is * still pending */ #define TCP_ASYNC_FAILED (1<<5) /* An async connect finally failed */ | > > > > > > | | 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | #define SOCKET_PENDING (1<<3) /* A message has been sent for this * socket */ #define TCP_ASYNC_PENDING (1<<4) /* TcpConnect was called to * process an async connect. This * flag indicates that reentry is * still pending */ #define TCP_ASYNC_FAILED (1<<5) /* An async connect finally failed */ /* * These bits may be ORed together into the "testFlags" field of a TcpState * structure. */ #define TCP_ASYNC_TEST_MODE (1<<0) /* Async testing activated * Do not automatically continue connection * process */ /* * The following structure is what is added to the Tcl event queue when a * socket event occurs. */ |
︙ | ︙ | |||
608 609 610 611 612 613 614 | * In socket test mode do not continue with the connect * Exceptions are: * - Call by recv/send and blocking socket * (errorCodePtr != NULL && ! flags & TCP_NONBLOCKING) * - Call by the event queue (errorCodePtr == NULL) */ | | | 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 | * In socket test mode do not continue with the connect * Exceptions are: * - Call by recv/send and blocking socket * (errorCodePtr != NULL && ! flags & TCP_NONBLOCKING) * - Call by the event queue (errorCodePtr == NULL) */ if ( (statePtr->testFlags & TCP_ASYNC_TEST_MODE) && errorCodePtr != NULL && (statePtr->flags & TCP_NONBLOCKING)) { *errorCodePtr = EWOULDBLOCK; return -1; } /* * Be sure to disable event servicing so we are truly modal. |
︙ | ︙ | |||
1136 1137 1138 1139 1140 1141 1142 | static int TcpSetOptionProc( ClientData instanceData, /* Socket state. */ Tcl_Interp *interp, /* For error reporting - can be NULL. */ const char *optionName, /* Name of the option to set. */ const char *value) /* New value for option. */ { | < < < < < < < < < < < < < < < < < | 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 | static int TcpSetOptionProc( ClientData instanceData, /* Socket state. */ Tcl_Interp *interp, /* For error reporting - can be NULL. */ const char *optionName, /* Name of the option to set. */ const char *value) /* New value for option. */ { #ifdef TCL_FEATURE_KEEPALIVE_NAGLE TcpState *statePtr = instanceData; SOCKET sock; #endif /*TCL_FEATURE_KEEPALIVE_NAGLE*/ /* * Check that WinSock is initialized; do not call it if not, to prevent * system crashes. This can happen at exit time if the exit handler for * WinSock ran before other exit handlers that want to use sockets. */ if (!SocketsEnabled()) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "winsock is not initialized", -1)); } return TCL_ERROR; } #ifdef TCL_FEATURE_KEEPALIVE_NAGLE #error "TCL_FEATURE_KEEPALIVE_NAGLE not reviewed for whether to treat statePtr->sockets as single fd or list" sock = statePtr->sockets->fd; if (!strcasecmp(optionName, "-keepalive")) { BOOL val = FALSE; int boolVar, rtn; |
︙ | ︙ | |||
1284 1285 1286 1287 1288 1289 1290 | return TCL_ERROR; } /* * Go one step in async connect * If any error is thrown save it as backround error to report eventually below */ | | | 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 | return TCL_ERROR; } /* * Go one step in async connect * If any error is thrown save it as backround error to report eventually below */ if (! (statePtr->testFlags & TCP_ASYNC_TEST_MODE) ) { WaitForConnect(statePtr, NULL); } sock = statePtr->sockets->fd; if (optionName != NULL) { len = strlen(optionName); } |
︙ | ︙ |