From a9dbadf46a6887f08b95f97dce3815020e7e0519 Mon Sep 17 00:00:00 2001 From: pooryorick Date: Mon, 3 Oct 2016 01:10:16 +0000 Subject: Fix [2bf561854c55a], interp alias to command whose name is the empty string. --- generic/tclInterp.c | 11 +++-------- tests/interp.test | 11 +++++++++++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/generic/tclInterp.c b/generic/tclInterp.c index a2de658..1bfe76a 100644 --- a/generic/tclInterp.c +++ b/generic/tclInterp.c @@ -660,14 +660,9 @@ NRInterpCmd( if (masterInterp == NULL) { return TCL_ERROR; } - if (TclGetString(objv[5])[0] == '\0') { - if (objc == 6) { - return AliasDelete(interp, slaveInterp, objv[3]); - } - } else { - return AliasCreate(interp, slaveInterp, masterInterp, objv[3], - objv[5], objc - 6, objv + 6); - } + + return AliasCreate(interp, slaveInterp, masterInterp, objv[3], + objv[5], objc - 6, objv + 6); } goto aliasArgs; } diff --git a/tests/interp.test b/tests/interp.test index 34b5bf9..ed76f1a 100644 --- a/tests/interp.test +++ b/tests/interp.test @@ -606,6 +606,17 @@ test interp-14.10 {testing interp-alias: error messages} -setup { invoked from within "a 1"} +test interp-14.11 {{interp alias} {target named the empty string} {bug 2bf56185}} -setup { + set interp [interp create [info cmdcount]] + interp eval $interp { + proc {} args {return $args} + } + +} -body { + interp alias {} p1 $interp {} + p1 one two three +} -result {one two three} + # part 15: testing file sharing test interp-15.1 {testing file sharing} { catch {interp delete z} -- cgit v0.12 From 8c066a970f11314588d9390f553f6fd3cac5973c Mon Sep 17 00:00:00 2001 From: pooryorick Date: Mon, 3 Oct 2016 16:49:58 +0000 Subject: Fix documentation of [expr] operators, replacing "divisor" with "dividend" --- doc/expr.n | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/expr.n b/doc/expr.n index b76b6a2..e25515d 100644 --- a/doc/expr.n +++ b/doc/expr.n @@ -133,15 +133,15 @@ Exponentiation. Valid for any numeric operands. Multiply, divide, remainder. None of these operators may be applied to string operands, and remainder may be applied only to integers. -The remainder will always have the same sign as the divisor and +The remainder always has the same sign as the divisor and an absolute value smaller than the absolute value of the divisor. .RS .PP When applied to integers, the division and remainder operators can be considered to partition the number line into a sequence of equal-sized adjacent non-overlapping pieces where each piece is the size of the divisor; -the division result identifies which piece the divisor lay within, and the -remainder result identifies where within that piece the divisor lay. A +the division result identifies which piece the dividend lies within, and the +remainder result identifies where within that piece the dividend lies. A consequence of this is that the result of .QW "-57 \fB/\fR 10" is always -6, and the result of -- cgit v0.12 From a629b0ba31444cfbdafc441e30d4a6df9b14126b Mon Sep 17 00:00:00 2001 From: max Date: Tue, 4 Oct 2016 13:31:49 +0000 Subject: When opening a server socket on an ephemeral port, make sure that the port number that gets picked for IPv4 is also available on IPv6. If not, start all over for up to ten times to find a port number that is available on both protocols. --- unix/tclUnixSock.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c index 8167077..f7bd0be 100644 --- a/unix/tclUnixSock.c +++ b/unix/tclUnixSock.c @@ -1429,7 +1429,7 @@ Tcl_OpenTcpServer( * clients. */ ClientData acceptProcData) /* Data for the callback. */ { - int status = 0, sock = -1, reuseaddr = 1, chosenport = 0; + int status = 0, sock = -1, reuseaddr = 1, chosenport; struct addrinfo *addrlist = NULL, *addrPtr; /* socket address */ TcpState *statePtr = NULL; char channelName[SOCK_CHAN_LENGTH]; @@ -1444,6 +1444,37 @@ Tcl_OpenTcpServer( enum { LOOKUP, SOCKET, BIND, LISTEN } howfar = LOOKUP; int my_errno = 0; + /* + * If we were called with port 0 to listen on a random port number, we + * copy the port number from the first member of the addrinfo list to all + * subsequent members, so that IPv4 and IPv6 listen on the same port. This + * might fail to bind() with EADDRINUSE if a port is free on the first + * address family in the list but already used on the other. In this case + * we revert everything we've done so far and start from scratch hoping + * that next time we'll find a port number that is usable on all address + * families. We try this at most MAXRETRY times to avoid an endless loop + * if all ports are taken. + */ + int retry = 0; +#define MAXRETRY 10 + + repeat: + if (retry > 0) { + if (statePtr != NULL) { + TcpCloseProc(statePtr, NULL); + statePtr = NULL; + } + if (addrlist != NULL) { + freeaddrinfo(addrlist); + addrlist = NULL; + } + if (retry >= MAXRETRY) { + goto error; + } + } + retry++; + chosenport = 0; + if (!TclCreateSocketAddress(interp, &addrlist, myHost, port, 1, &errorMsg)) { my_errno = errno; goto error; @@ -1512,6 +1543,9 @@ Tcl_OpenTcpServer( } close(sock); sock = -1; + if (port == 0 && errno == EADDRINUSE) { + goto repeat; + } continue; } if (port == 0 && chosenport == 0) { @@ -1535,6 +1569,9 @@ Tcl_OpenTcpServer( } close(sock); sock = -1; + if (port == 0 && errno == EADDRINUSE) { + goto repeat; + } continue; } if (statePtr == NULL) { -- cgit v0.12