Tcl Source Code

Changes On Branch bug-581937ab1e
Login

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

Changes In Branch bug-581937ab1e Excluding Merge-Ins

This is equivalent to a diff from 1dfe1390d8 to 29adf4bac3

2014-04-02
13:33
Fix bug [581937ab1e]: fire readable event on async socket connect failure check-in: 37dce67f70 user: oehhar tags: core-8-5-branch
12:43
Fix bug [581937ab1e]: fire readable event on async socket connect failure Closed-Leaf check-in: 29adf4bac3 user: oehhar tags: bug-581937ab1e
10:02
Fix bug [336441ed59]: Win socket stall on quick termination of async socket connect check-in: 1dfe1390d8 user: oehhar tags: core-8-5-branch
09:54
Test to demonstrate bug [336441ed59]. Depends on timing and will not always fire but is better than ... check-in: 22a6175c07 user: oehhar tags: bug-336441ed59
2014-03-31
15:23
Cherry-pick [c54059aaad] from trunk: Added support for reporting TEA-like info via pkg-config. Add ... check-in: 70b7d58cae user: jan.nijtmans tags: core-8-5-branch
2014-03-24
11:03
Fire also readable event on final async connect failure. Armor WaitForSocketEvent by access signal a... check-in: f1d2f6dbad user: oehhar tags: bug-13d3af3ad5

Changes to tests/socket.test.

62
63
64
65
66
67
68




69
70
71
72
73
74
75

package require tcltest 2
namespace import -force ::tcltest::*

# Some tests require the testthread and exec commands
testConstraint testthread [llength [info commands testthread]]
testConstraint exec [llength [info commands exec]]





# If remoteServerIP or remoteServerPort are not set, check in the
# environment variables for externally set values.
#

if {![info exists remoteServerIP]} {
    if {[info exists env(remoteServerIP)]} {







>
>
>
>







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

package require tcltest 2
namespace import -force ::tcltest::*

# Some tests require the testthread and exec commands
testConstraint testthread [llength [info commands testthread]]
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)} }

# If remoteServerIP or remoteServerPort are not set, check in the
# environment variables for externally set values.
#

if {![info exists remoteServerIP]} {
    if {[info exists env(remoteServerIP)]} {
921
922
923
924
925
926
927













928
929
930
931
932
933
934
    set s [socket -async 255.255.255.255 43434]
    fileevent $s writable {set x writable}
    vwait x
    catch {close $s}
    after cancel $a1
    set x
} writable














test socket-9.1 {testing spurious events} {socket} {
    set len 0
    set spurious 0
    set done 0
    proc readlittle {s} {
	global spurious done len







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







925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
    set s [socket -async 255.255.255.255 43434]
    fileevent $s writable {set x writable}
    vwait x
    catch {close $s}
    after cancel $a1
    set x
} writable

test socket-8.3 {testing fileevent readable on failed async socket connect} {socket} {
    # Test for bug 581937ab1e

    set a1 [after 5000 {set x timeout}]
    # This connect should fail
    set s [socket -async localhost [randport]]
    fileevent $s readable {set x readable}
    vwait x
    catch {close $s}
    after cancel $a1
    set x
} readable

test socket-9.1 {testing spurious events} {socket} {
    set len 0
    set spurious 0
    set done 0
    proc readlittle {s} {
	global spurious done len

Changes to win/tclWinSock.c.

715
716
717
718
719
720
721









722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748

749
750
751
752
753
754
755

756
757
758
759
760
761
762
763
764
	 * trying to do unwind protection.
	 */

	Tcl_Time blockTime = { 0, 0 };
	Tcl_SetMaxBlockTime(&blockTime);
	mask |= TCL_READABLE|TCL_WRITABLE;
    } else if (events & FD_READ) {









	fd_set readFds;
	struct timeval timeout;

	/*
	 * We must check to see if data is really available, since someone
	 * could have consumed the data in the meantime. Turn off async
	 * notification so select will work correctly. If the socket is still
	 * readable, notify the channel driver, otherwise reset the async
	 * select handler and keep waiting.
	 */

	SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
		(WPARAM) UNSELECT, (LPARAM) infoPtr);

	FD_ZERO(&readFds);
	FD_SET(infoPtr->socket, &readFds);
	timeout.tv_usec = 0;
	timeout.tv_sec = 0;

	if (select(0, &readFds, NULL, NULL, &timeout) != 0) {
	    mask |= TCL_READABLE;
	} else {
	    infoPtr->readyEvents &= ~(FD_READ);
	    SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
		    (WPARAM) SELECT, (LPARAM) infoPtr);
	}
    }

    if (events & (FD_WRITE | FD_CONNECT)) {
	mask |= TCL_WRITABLE;
	if (events & FD_CONNECT && infoPtr->lastError != NO_ERROR) {
	    /*
	     * Connect errors should also fire the readable handler.
	     */


	    mask |= TCL_READABLE;
	}
    }

    if (mask) {
	Tcl_NotifyChannel(infoPtr->channel, mask);
    }
    return 1;
}







>
>
>
>
>
>
>
>
>
|
|

|
|
|
|
|
|
|

|
|

|
|
|
|

|
|
|
|
|
|
|
|
>
|
<
<
|
|
|

>
|
<







715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759


760
761
762
763
764
765

766
767
768
769
770
771
772
	 * trying to do unwind protection.
	 */

	Tcl_Time blockTime = { 0, 0 };
	Tcl_SetMaxBlockTime(&blockTime);
	mask |= TCL_READABLE|TCL_WRITABLE;
    } else if (events & FD_READ) {
	/*
	 * Throw the readable event if an async connect failed.
	 */

	if (infoPtr->lastError) {

	    mask |= TCL_READABLE;
	    
	} else {
	    fd_set readFds;
	    struct timeval timeout;

	    /*
	     * We must check to see if data is really available, since someone
	     * could have consumed the data in the meantime. Turn off async
	     * notification so select will work correctly. If the socket is still
	     * readable, notify the channel driver, otherwise reset the async
	     * select handler and keep waiting.
	     */

	    SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
		    (WPARAM) UNSELECT, (LPARAM) infoPtr);

	    FD_ZERO(&readFds);
	    FD_SET(infoPtr->socket, &readFds);
	    timeout.tv_usec = 0;
	    timeout.tv_sec = 0;

	    if (select(0, &readFds, NULL, NULL, &timeout) != 0) {
		mask |= TCL_READABLE;
	    } else {
		infoPtr->readyEvents &= ~(FD_READ);
		SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
			(WPARAM) SELECT, (LPARAM) infoPtr);
	    }
	}
    }



    /*
     * writable event
     */

    if (events & FD_WRITE) {
	mask |= TCL_WRITABLE;

    }

    if (mask) {
	Tcl_NotifyChannel(infoPtr->channel, mask);
    }
    return 1;
}
2405
2406
2407
2408
2409
2410
2411

2412
2413


2414
2415


2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431

		/*
		 * Remember any error that occurred so we can report
		 * connection failures.
		 */

		if (error != ERROR_SUCCESS) {

		    TclWinConvertWSAError((DWORD) error);
		    infoPtr->lastError = Tcl_GetErrno();


		}
	    }



	    if (infoPtr->flags & SOCKET_ASYNC_CONNECT) {
		infoPtr->flags &= ~(SOCKET_ASYNC_CONNECT);
		if (error != ERROR_SUCCESS) {
		    TclWinConvertWSAError((DWORD) error);
		    infoPtr->lastError = Tcl_GetErrno();
		}
		infoPtr->readyEvents |= FD_WRITE;
	    }
	    infoPtr->readyEvents |= event;

	    /*
	     * Wake up the Main Thread.
	     */

	    SetEvent(tsdPtr->readyEvent);







>


>
>

|
>
>

<
<
<
<
<
|
<
|







2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429





2430

2431
2432
2433
2434
2435
2436
2437
2438

		/*
		 * Remember any error that occurred so we can report
		 * connection failures.
		 */

		if (error != ERROR_SUCCESS) {
		    /* Async Connect error */
		    TclWinConvertWSAError((DWORD) error);
		    infoPtr->lastError = Tcl_GetErrno();
		    /* Fire also readable event on connect failure */
		    infoPtr->readyEvents |= FD_READ;
		}

		/* fire writable event on connect */
		infoPtr->readyEvents |= FD_WRITE;






	    }


	    infoPtr->readyEvents |= event;

	    /*
	     * Wake up the Main Thread.
	     */

	    SetEvent(tsdPtr->readyEvent);