Check-in [5362b4849e]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:improvements regarding [9ba84a8a76]
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5362b4849e8f86731466deda1ea8d3d884bc5bc6
User & Date: chw 2019-11-08 22:48:44
References
2019-11-08
23:04
improvements regarding [5362b4849e] check-in: 56ed33b76a user: chw tags: trunk
Context
2019-11-08
23:04
improvements regarding [5362b4849e] check-in: 56ed33b76a user: chw tags: trunk
22:48
improvements regarding [9ba84a8a76] check-in: 5362b4849e user: chw tags: trunk
09:34
more tcl upstream changes check-in: d330ab7f7d user: chw tags: trunk
Changes

Changes to jni/tcl/unix/tclUnixSock.c.

44
45
46
47
48
49
50

51
52
53
54
55
56
57
...
608
609
610
611
612
613
614



615
616
617
618
619
620
621
....
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
....
1385
1386
1387
1388
1389
1390
1391

1392
1393
1394
1395
1396
1397
1398
....
1460
1461
1462
1463
1464
1465
1466

1467
1468
1469
1470
1471
1472
1473
....
1642
1643
1644
1645
1646
1647
1648

1649
1650
1651
1652
1653
1654
1655
....
1712
1713
1714
1715
1716
1717
1718
























1719
1720
1721
1722
1723
1724
1725
....
1735
1736
1737
1738
1739
1740
1741

1742
1743
1744
1745
1746
1747
1748
 */

typedef struct TcpState TcpState;

typedef struct TcpFdList {
    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
................................................................................
     */

    for (fds = &statePtr->fds; fds != NULL; fds = fds->next) {
	if (fds->fd < 0) {
	    continue;
	}
	Tcl_DeleteFileHandler(fds->fd);



	if (close(fds->fd) < 0) {
	    errorCode = errno;
	}

    }
    fds = statePtr->fds.next;
    while (fds != NULL) {
................................................................................
        TclUnixSetBlockingMode(statePtr->fds.fd, statePtr->cachedBlocking);

        if (error != 0) {
            SET_BITS(statePtr->flags, TCP_ASYNC_FAILED);
        }

        /*
         * We need to forward the writable event that brought us here, bcasue
         * upon reading of getsockopt(SO_ERROR), at least some OSes clear the
         * writable state from the socket, and so a subsequent select() on
         * behalf of a script level [fileevent] would not fire. It doesn't
         * hurt that this is also called in the successful case and will save
         * the event mechanism one roundtrip through select().
         */

................................................................................
    statePtr = ckalloc(sizeof(TcpState));
    memset(statePtr, 0, sizeof(TcpState));
    statePtr->flags = async ? TCP_ASYNC_CONNECT : 0;
    statePtr->cachedBlocking = TCL_MODE_BLOCKING;
    statePtr->addrlist = addrlist;
    statePtr->myaddrlist = myaddrlist;
    statePtr->fds.fd = -1;


    /*
     * Create a new client socket and wrap it in a channel.
     */

    if (TcpConnect(interp, statePtr) != TCL_OK) {
        TcpCloseProc(statePtr, NULL);
................................................................................
{
    TcpState *statePtr;
    char channelName[SOCK_CHAN_LENGTH];

    statePtr = ckalloc(sizeof(TcpState));
    memset(statePtr, 0, sizeof(TcpState));
    statePtr->fds.fd = PTR2INT(sock);

    statePtr->flags = 0;

    sprintf(channelName, SOCK_TEMPLATE, (long)statePtr);

    statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    statePtr, mode);
    if (Tcl_SetChannelOption(NULL, statePtr->channel, "-translation",
................................................................................
            newfds = &statePtr->fds;
        } else {
            newfds = ckalloc(sizeof(TcpFdList));
            memset(newfds, (int) 0, sizeof(TcpFdList));
            fds->next = newfds;
        }
        newfds->fd = sock;

        newfds->statePtr = statePtr;
        fds = newfds;

        /*
         * Set up the callback mechanism for accepting connections from new
         * clients.
         */
................................................................................
    socklen_t len;		/* For accept interface */
    char channelName[SOCK_CHAN_LENGTH];
    char host[NI_MAXHOST], port[NI_MAXSERV];

    len = sizeof(addr);
    newsock = accept(fds->fd, &addr.sa, &len);
    if (newsock < 0) {
























	return;
    }

    /*
     * Ticket [c6897e6e6a].
     */

................................................................................

    (void) fcntl(newsock, F_SETFD, FD_CLOEXEC);

    newSockState = ckalloc(sizeof(TcpState));
    memset(newSockState, 0, sizeof(TcpState));
    newSockState->flags = 0;
    newSockState->fds.fd = newsock;


    sprintf(channelName, SOCK_TEMPLATE, (long) newSockState);
    newSockState->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    newSockState, TCL_READABLE | TCL_WRITABLE);

    Tcl_SetChannelOption(NULL, newSockState->channel, "-translation",
	    "auto crlf");







>







 







>
>
>







 







|







 







>







 







>







 







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
...
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
....
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
....
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
....
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
....
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
....
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
....
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
 */

typedef struct TcpState TcpState;

typedef struct TcpFdList {
    TcpState *statePtr;
    int fd;
    int spareFd;
    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
................................................................................
     */

    for (fds = &statePtr->fds; fds != NULL; fds = fds->next) {
	if (fds->fd < 0) {
	    continue;
	}
	Tcl_DeleteFileHandler(fds->fd);
	if (fds->spareFd != -1) {
	    close(fds->spareFd);
	}
	if (close(fds->fd) < 0) {
	    errorCode = errno;
	}

    }
    fds = statePtr->fds.next;
    while (fds != NULL) {
................................................................................
        TclUnixSetBlockingMode(statePtr->fds.fd, statePtr->cachedBlocking);

        if (error != 0) {
            SET_BITS(statePtr->flags, TCP_ASYNC_FAILED);
        }

        /*
         * We need to forward the writable event that brought us here, because
         * upon reading of getsockopt(SO_ERROR), at least some OSes clear the
         * writable state from the socket, and so a subsequent select() on
         * behalf of a script level [fileevent] would not fire. It doesn't
         * hurt that this is also called in the successful case and will save
         * the event mechanism one roundtrip through select().
         */

................................................................................
    statePtr = ckalloc(sizeof(TcpState));
    memset(statePtr, 0, sizeof(TcpState));
    statePtr->flags = async ? TCP_ASYNC_CONNECT : 0;
    statePtr->cachedBlocking = TCL_MODE_BLOCKING;
    statePtr->addrlist = addrlist;
    statePtr->myaddrlist = myaddrlist;
    statePtr->fds.fd = -1;
    statePtr->fds.spareFd = -1;

    /*
     * Create a new client socket and wrap it in a channel.
     */

    if (TcpConnect(interp, statePtr) != TCL_OK) {
        TcpCloseProc(statePtr, NULL);
................................................................................
{
    TcpState *statePtr;
    char channelName[SOCK_CHAN_LENGTH];

    statePtr = ckalloc(sizeof(TcpState));
    memset(statePtr, 0, sizeof(TcpState));
    statePtr->fds.fd = PTR2INT(sock);
    statePtr->fds.spareFd = -1;
    statePtr->flags = 0;

    sprintf(channelName, SOCK_TEMPLATE, (long)statePtr);

    statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    statePtr, mode);
    if (Tcl_SetChannelOption(NULL, statePtr->channel, "-translation",
................................................................................
            newfds = &statePtr->fds;
        } else {
            newfds = ckalloc(sizeof(TcpFdList));
            memset(newfds, (int) 0, sizeof(TcpFdList));
            fds->next = newfds;
        }
        newfds->fd = sock;
        newfds->spareFd = dup(sock);
        newfds->statePtr = statePtr;
        fds = newfds;

        /*
         * Set up the callback mechanism for accepting connections from new
         * clients.
         */
................................................................................
    socklen_t len;		/* For accept interface */
    char channelName[SOCK_CHAN_LENGTH];
    char host[NI_MAXHOST], port[NI_MAXSERV];

    len = sizeof(addr);
    newsock = accept(fds->fd, &addr.sa, &len);
    if (newsock < 0) {

	/*
	 * Last resort: try to cleanup the listen backlog. If that
	 * fails, a busy event loop is the most likely outcome.
	 * Due to process semantic of the file descriptor table
	 * this strategy is inherently not threadsafe. It could
	 * be remedied if there was a system call which combines
	 * accept() with dup() using a spare pre-allocated file
	 * descriptor. Otherwise, ALL system calls producing a
	 * new file descriptor would require to be mutexed in order
	 * to guarantee availability of that spare file descriptor.
	 */

	if (errno == EMFILE || errno == ENFILE) {
	    if (fds->spareFd != -1) {
		close(fds->spareFd);
		len = sizeof(addr);
		fds->spareFd = accept(fds->fd, &addr.sa, &len);
		if (fds->spareFd >= 0) {
		    close(fds->spareFd);
		    fds->spareFd = dup(fds->fd);
		}
	    }
	}
	return;
    }

    /*
     * Ticket [c6897e6e6a].
     */

................................................................................

    (void) fcntl(newsock, F_SETFD, FD_CLOEXEC);

    newSockState = ckalloc(sizeof(TcpState));
    memset(newSockState, 0, sizeof(TcpState));
    newSockState->flags = 0;
    newSockState->fds.fd = newsock;
    newSockState->fds.spareFd = -1;

    sprintf(channelName, SOCK_TEMPLATE, (long) newSockState);
    newSockState->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    newSockState, TCL_READABLE | TCL_WRITABLE);

    Tcl_SetChannelOption(NULL, newSockState->channel, "-translation",
	    "auto crlf");