Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge 9.0 - Fix [40b1814b93] and [7c2716733a] Window handle use-after-frees. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk | main |
Files: | files | file ages | folders |
SHA3-256: |
54eb90319d986d4b3edf9cffa7f7364c |
User & Date: | apnadkarni 2025-06-25 16:41:27.794 |
Context
2025-06-26
| ||
07:53 | Change bytecode flag names to match their related instruction check-in: 37bed52197 user: dkf tags: trunk, main | |
2025-06-25
| ||
16:41 | Merge 9.0 - Fix [40b1814b93] and [7c2716733a] Window handle use-after-frees. check-in: 54eb90319d user: apnadkarni tags: trunk, main | |
16:23 | Fix [7c2716733a] - use after free on Windows pipe handles check-in: a9351d85f3 user: apnadkarni tags: core-9-0-branch | |
12:20 | Merge 9.0 check-in: f8b2589dc1 user: jan.nijtmans tags: trunk, main | |
Changes
Changes to tests/aaa_exit.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. if {"::tcltest" ni [namespace children]} { package require tcltest 2.5 namespace import -force ::tcltest::* } | > > > > | | | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. if {"::tcltest" ni [namespace children]} { package require tcltest 2.5 namespace import -force ::tcltest::* } testConstraint noappverifier [expr { [llength [info commands testappverifierpresent]] == 0 || ![testappverifierpresent]}] test exit-1.1 {normal, quick exit} -constraints noappverifier -body { set f [open "|[interpreter] << \"exec [interpreter] << {set ::env(TCL_FINALIZE_ON_EXIT) 0;exit}\"" r] set aft [after 1000 {set done "Quick exit hangs !!!"}] fileevent $f readable {after cancel $aft;set done OK} vwait done if {$done != "OK"} { fconfigure $f -blocking 0 close $f } else { if {[catch {close $f} err]} { set done "Quick exit misbehaves: $err" } } set done } -result OK test exit-1.2 {full-finalized exit} -constraints noappverifier -body { set f [open "|[interpreter] << \"exec [interpreter] << {set ::env(TCL_FINALIZE_ON_EXIT) 1;exit}\"" r] set aft [after 1000 {set done "Full-finalized exit hangs !!!"}] fileevent $f readable {after cancel $aft;set done OK} vwait done if {$done != "OK"} { fconfigure $f -blocking 0 close $f } else { if {[catch {close $f} err]} { set done "Full-finalized exit misbehaves: $err" } } set done } -result OK # cleanup ::tcltest::cleanupTests return |
Changes to tests/chanio.test.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # this file, and for a DISCLAIMER OF ALL WARRANTIES. if {"::tcltest" ni [namespace children]} { package require tcltest 2.5 namespace import -force ::tcltest::* } namespace eval ::tcl::test::io { if {"::tcltest" ni [namespace children]} { package require tcltest 2.5 namespace import -force ::tcltest::* } | > > > > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # this file, and for a DISCLAIMER OF ALL WARRANTIES. if {"::tcltest" ni [namespace children]} { package require tcltest 2.5 namespace import -force ::tcltest::* } testConstraint noappverifier [expr { [llength [info commands testappverifierpresent]] == 0 || ![testappverifierpresent]}] namespace eval ::tcl::test::io { if {"::tcltest" ni [namespace children]} { package require tcltest 2.5 namespace import -force ::tcltest::* } |
︙ | ︙ | |||
1035 1036 1037 1038 1039 1040 1041 | list [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line } -cleanup { chan close $f } -result [list 8 "there一ok" 11 "丁more bytes" 4 "here"] test chan-io-6.56 {Tcl_GetsObj: incomplete lines should disable file events} -setup { update variable x {} | | | 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 | list [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line } -cleanup { chan close $f } -result [list 8 "there一ok" 11 "丁more bytes" 4 "here"] test chan-io-6.56 {Tcl_GetsObj: incomplete lines should disable file events} -setup { update variable x {} } -constraints {stdio fileevent noappverifier} -body { set f [openpipe w+ $path(cat)] chan configure $f -buffering none chan puts -nonewline $f "foobar" chan configure $f -blocking 0 after 500 [namespace code { lappend x timeout }] |
︙ | ︙ | |||
1472 1473 1474 1475 1476 1477 1478 | chan read $f } -cleanup { chan close $f } -result "abcd\ndef\nfgh" test chan-io-13.6 {TranslateInputEOL: auto mode: saw cr in last segment} -setup { variable x {} variable y {} | | | 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 | chan read $f } -cleanup { chan close $f } -result "abcd\ndef\nfgh" test chan-io-13.6 {TranslateInputEOL: auto mode: saw cr in last segment} -setup { variable x {} variable y {} } -constraints {stdio testchannel fileevent noappverifier} -body { # (chanPtr->flags & INPUT_SAW_CR) # This test may fail on slower machines. set f [openpipe w+ $path(cat)] chan configure $f -blocking 0 -buffering none -translation {auto lf} chan event $f read [namespace code { lappend x [chan read $f] [testchannel queuedcr $f] }] |
︙ | ︙ | |||
2194 2195 2196 2197 2198 2199 2200 | set cat [makeFile { fconfigure stdout -buffering line while {[gets stdin line] >= 0} {puts $line} puts DONE exit 0 } cat.tcl] variable done | | | 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 | set cat [makeFile { fconfigure stdout -buffering line while {[gets stdin line] >= 0} {puts $line} puts DONE exit 0 } cat.tcl] variable done } -constraints noappverifier -body { set ff [openpipe r+ $cat] puts $ff Hey close $ff w set timer [after 1000 [namespace code {set done Failed}]] set acc {} fileevent $ff readable [namespace code { if {[gets $ff line] < 0} { |
︙ | ︙ |
Changes to tests/clock.test.
︙ | ︙ | |||
21 22 23 24 25 26 27 28 29 30 31 32 33 34 | if {[catch { ::tcltest::loadTestedCommands }]} { # nothing to be done (registry loaded on demand) } } package require msgcat 1.4 testConstraint detroit \ [expr {![catch {clock format 0 -timezone :America/Detroit -format %z}]}] testConstraint y2038 \ [expr {[clock format 2158894800 -format %z -timezone :America/Detroit] eq {-0400}}] | > > > > > > > | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | if {[catch { ::tcltest::loadTestedCommands }]} { # nothing to be done (registry loaded on demand) } } # Application Verifier hooks system calls in a way that locale # detection fails. Disable tests that depend on that if # it is running. testConstraint noappverifier [expr { [llength [info commands testappverifierpresent]] == 0 || ![testappverifierpresent]}] package require msgcat 1.4 testConstraint detroit \ [expr {![catch {clock format 0 -timezone :America/Detroit -format %z}]}] testConstraint y2038 \ [expr {[clock format 2158894800 -format %z -timezone :America/Detroit] eq {-0400}}] |
︙ | ︙ | |||
35939 35940 35941 35942 35943 35944 35945 | rename test_add_dst {} } -result {} # END testcases30 test clock-31.1 {system locale} \ | | | 35946 35947 35948 35949 35950 35951 35952 35953 35954 35955 35956 35957 35958 35959 35960 | rename test_add_dst {} } -result {} # END testcases30 test clock-31.1 {system locale} \ -constraints {win noappverifier} \ -setup { namespace eval ::tcl::clock { namespace import -force ::testClock::registry } set noreg [info exists ::tcl::clock::NoRegistry] if {$noreg} {unset ::tcl::clock::NoRegistry} ::tcl::clock::ClearCaches |
︙ | ︙ | |||
35962 35963 35964 35965 35966 35967 35968 | if {$noreg} {set ::tcl::clock::NoRegistry {}} ::tcl::clock::ClearCaches } \ -result [clock format 0 -timezone :UTC -locale current \ -format {%d-%b-%Y}] test clock-31.2 {system locale} \ | | | 35969 35970 35971 35972 35973 35974 35975 35976 35977 35978 35979 35980 35981 35982 35983 | if {$noreg} {set ::tcl::clock::NoRegistry {}} ::tcl::clock::ClearCaches } \ -result [clock format 0 -timezone :UTC -locale current \ -format {%d-%b-%Y}] test clock-31.2 {system locale} \ -constraints {win noappverifier} \ -setup { namespace eval ::tcl::clock { namespace import -force ::testClock::registry } set noreg [info exists ::tcl::clock::NoRegistry] if {$noreg} {unset ::tcl::clock::NoRegistry} ::tcl::clock::ClearCaches |
︙ | ︙ | |||
35985 35986 35987 35988 35989 35990 35991 | if {$noreg} {set ::tcl::clock::NoRegistry {}} ::tcl::clock::ClearCaches } \ -result [clock format 0 -timezone :UTC -locale current \ -format {the %d' day of %B %Y}] test clock-31.3 {system locale} \ | | | 35992 35993 35994 35995 35996 35997 35998 35999 36000 36001 36002 36003 36004 36005 36006 | if {$noreg} {set ::tcl::clock::NoRegistry {}} ::tcl::clock::ClearCaches } \ -result [clock format 0 -timezone :UTC -locale current \ -format {the %d' day of %B %Y}] test clock-31.3 {system locale} \ -constraints {win noappverifier} \ -setup { namespace eval ::tcl::clock { namespace import -force ::testClock::registry } set noreg [info exists ::tcl::clock::NoRegistry] if {$noreg} {unset ::tcl::clock::NoRegistry} ::tcl::clock::ClearCaches |
︙ | ︙ | |||
36008 36009 36010 36011 36012 36013 36014 | if {$noreg} {set ::tcl::clock::NoRegistry {}} ::tcl::clock::ClearCaches } \ -result [clock format 0 -timezone :UTC -locale current \ -format {%l:%M:%S %p}] test clock-31.4 {system locale} \ | | | 36015 36016 36017 36018 36019 36020 36021 36022 36023 36024 36025 36026 36027 36028 36029 | if {$noreg} {set ::tcl::clock::NoRegistry {}} ::tcl::clock::ClearCaches } \ -result [clock format 0 -timezone :UTC -locale current \ -format {%l:%M:%S %p}] test clock-31.4 {system locale} \ -constraints {win noappverifier} \ -setup { namespace eval ::tcl::clock { namespace import -force ::testClock::registry } set noreg [info exists ::tcl::clock::NoRegistry] if {$noreg} {unset ::tcl::clock::NoRegistry} if { [info exists env(TZ)] } { |
︙ | ︙ | |||
36045 36046 36047 36048 36049 36050 36051 | if {$noreg} {set ::tcl::clock::NoRegistry {}} ::tcl::clock::ClearCaches } \ -result [clock format 0 -locale current -timezone EST5 \ -format {%d-%b-%Y}] test clock-31.5 {system locale} \ | | | 36052 36053 36054 36055 36056 36057 36058 36059 36060 36061 36062 36063 36064 36065 36066 | if {$noreg} {set ::tcl::clock::NoRegistry {}} ::tcl::clock::ClearCaches } \ -result [clock format 0 -locale current -timezone EST5 \ -format {%d-%b-%Y}] test clock-31.5 {system locale} \ -constraints {win noappverifier} \ -setup { namespace eval ::tcl::clock { namespace import -force ::testClock::registry } set noreg [info exists ::tcl::clock::NoRegistry] if {$noreg} {unset ::tcl::clock::NoRegistry} if { [info exists env(TZ)] } { |
︙ | ︙ | |||
36082 36083 36084 36085 36086 36087 36088 | } ::tcl::clock::ClearCaches } \ -result [clock format 0 -locale current -timezone EST5 \ -format {the %d' day of %B %Y}] test clock-31.6 {system locale} \ | | | 36089 36090 36091 36092 36093 36094 36095 36096 36097 36098 36099 36100 36101 36102 36103 | } ::tcl::clock::ClearCaches } \ -result [clock format 0 -locale current -timezone EST5 \ -format {the %d' day of %B %Y}] test clock-31.6 {system locale} \ -constraints {win noappverifier} \ -setup { namespace eval ::tcl::clock { namespace import -force ::testClock::registry } set noreg [info exists ::tcl::clock::NoRegistry] if {$noreg} {unset ::tcl::clock::NoRegistry} if { [info exists env(TZ)] } { |
︙ | ︙ | |||
37544 37545 37546 37547 37548 37549 37550 | clock format -86400 -timezone :localtime -format %Y } result] $result } \ -match regexp \ -result {0 1969|1 {localtime failed \(clock value may be too large/small to represent\)}} test clock-49.2 {regression test - missing time zone file (Bug 1237907)} \ | | | 37551 37552 37553 37554 37555 37556 37557 37558 37559 37560 37561 37562 37563 37564 37565 | clock format -86400 -timezone :localtime -format %Y } result] $result } \ -match regexp \ -result {0 1969|1 {localtime failed \(clock value may be too large/small to represent\)}} test clock-49.2 {regression test - missing time zone file (Bug 1237907)} \ -constraints {win noappverifier} \ -setup { # override the registry so that the test takes place in New York time namespace eval ::tcl::clock { namespace import -force ::testClock::registry } set noreg [info exists ::tcl::clock::NoRegistry] if {$noreg} {unset ::tcl::clock::NoRegistry} |
︙ | ︙ |
Changes to tests/cmdMZ.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # this file, and for a DISCLAIMER OF ALL WARRANTIES. if {"::tcltest" ni [namespace children]} { package require tcltest 2.5 namespace import -force ::tcltest::* } namespace eval ::tcl::test::cmdMZ { namespace import ::tcltest::cleanupTests namespace import ::tcltest::customMatch namespace import ::tcltest::makeFile namespace import ::tcltest::removeFile namespace import ::tcltest::temporaryDirectory namespace import ::tcltest::testConstraint | > > > > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # this file, and for a DISCLAIMER OF ALL WARRANTIES. if {"::tcltest" ni [namespace children]} { package require tcltest 2.5 namespace import -force ::tcltest::* } testConstraint noappverifier [expr { [llength [info commands testappverifierpresent]] == 0 || ![testappverifierpresent]}] namespace eval ::tcl::test::cmdMZ { namespace import ::tcltest::cleanupTests namespace import ::tcltest::customMatch namespace import ::tcltest::makeFile namespace import ::tcltest::removeFile namespace import ::tcltest::temporaryDirectory namespace import ::tcltest::testConstraint |
︙ | ︙ | |||
416 417 418 419 420 421 422 | } {1 {missing close-brace}} test cmdMZ-6.5a {Tcl_TimeRateObjCmd: result format and one iteration} { regexp {^\d+(?:\.\d+)? \ws/# 1 # \d+(?:\.\d+)? #/sec \d+(?:\.\d+)? net-ms$} [timerate {} 0] } 1 test cmdMZ-6.5b {Tcl_TimeRateObjCmd: result format without iterations} { regexp {^0 \ws/# 0 # 0 #/sec 0 net-ms$} [timerate {} 0 0] } 1 | > | > > | 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 | } {1 {missing close-brace}} test cmdMZ-6.5a {Tcl_TimeRateObjCmd: result format and one iteration} { regexp {^\d+(?:\.\d+)? \ws/# 1 # \d+(?:\.\d+)? #/sec \d+(?:\.\d+)? net-ms$} [timerate {} 0] } 1 test cmdMZ-6.5b {Tcl_TimeRateObjCmd: result format without iterations} { regexp {^0 \ws/# 0 # 0 #/sec 0 net-ms$} [timerate {} 0 0] } 1 test cmdMZ-6.6 { Tcl_TimeRateObjCmd: slower commands take longer, but it remains almost the same time of measurement } -constraints noappverifier -body { set m1 [timerate {_nrt_sleep 0.01} 50] set m2 [timerate {_nrt_sleep 1.00} 50] if {[testConstraint valgrind] && ([lindex $m1 0] >= 100 || [lindex $m1 2] <= 500)} { tcltest::Skip "too-slow-by-valgrind" } list [list \ [expr {[lindex $m1 0] < [lindex $m2 0]}] \ |
︙ | ︙ |
Changes to tests/env.test.
︙ | ︙ | |||
98 99 100 101 102 103 104 105 106 107 108 109 | proc cleanup1 {} { encodingrestore envrestore } variable keep { TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH PURE_PROG_NAME DISPLAY SHLIB_PATH SYSTEMDRIVE SYSTEMROOT DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH DYLD_NEW_LOCAL_SHARED_REGIONS DYLD_NO_FIX_PREBINDING MSYSTEM __CF_USER_TEXT_ENCODING SECURITYSESSIONID LANG WINDIR TERM | > | | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | proc cleanup1 {} { encodingrestore envrestore } # OANOCACHE comes from Application Verifier variable keep { TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH PURE_PROG_NAME DISPLAY SHLIB_PATH SYSTEMDRIVE SYSTEMROOT DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH DYLD_NEW_LOCAL_SHARED_REGIONS DYLD_NO_FIX_PREBINDING MSYSTEM __CF_USER_TEXT_ENCODING SECURITYSESSIONID LANG WINDIR TERM CommonProgramFiles CommonProgramFiles(x86) OANOCACHE ProgramFiles ProgramFiles(x86) CommonProgramW6432 ProgramW6432 PROCESSOR_ARCHITECTURE PROCESSOR_ARCHITEW6432 USERPROFILE WINECONFIGDIR WINEDATADIR WINEDLLDIR0 WINEHOMEDIR WINELOADER WINEUSERLOCALE WINEUSERNAME } variable printenvScript [makeFile [string map [list @keep@ [list $keep]] { |
︙ | ︙ |
Changes to win/tclWinInt.h.
︙ | ︙ | |||
72 73 74 75 76 77 78 | typedef struct TclPipeThreadInfo { HANDLE evControl; /* Auto-reset event used by the main thread to * signal when the pipe thread should attempt * to do read/write operation. Additionally * used as signal to stop (state set to -1) */ volatile LONG state; /* Indicates current state of the thread */ void *clientData; /* Referenced data of the main thread */ | < | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | typedef struct TclPipeThreadInfo { HANDLE evControl; /* Auto-reset event used by the main thread to * signal when the pipe thread should attempt * to do read/write operation. Additionally * used as signal to stop (state set to -1) */ volatile LONG state; /* Indicates current state of the thread */ void *clientData; /* Referenced data of the main thread */ } TclPipeThreadInfo; /* If pipe-workers will use some tcl subsystem, we can use Tcl_Alloc without * more overhead for finalize thread (should be executed anyway) * * #define _PTI_USE_CKALLOC 1 */ |
︙ | ︙ | |||
97 98 99 100 101 102 103 | PTI_STATE_STOP = 2, /* thread should stop work (owns TI structure) */ PTI_STATE_END = 4, /* thread should stop work (worker is busy) */ PTI_STATE_DOWN = 8 /* worker is down */ }; MODULE_SCOPE TclPipeThreadInfo * TclPipeThreadCreateTI(TclPipeThreadInfo **pipeTIPtr, | | | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | PTI_STATE_STOP = 2, /* thread should stop work (owns TI structure) */ PTI_STATE_END = 4, /* thread should stop work (worker is busy) */ PTI_STATE_DOWN = 8 /* worker is down */ }; MODULE_SCOPE TclPipeThreadInfo * TclPipeThreadCreateTI(TclPipeThreadInfo **pipeTIPtr, void *clientData); MODULE_SCOPE int TclPipeThreadWaitForSignal( TclPipeThreadInfo **pipeTIPtr); static inline void TclPipeThreadSignal( TclPipeThreadInfo **pipeTIPtr) { |
︙ | ︙ |
Changes to win/tclWinPipe.c.
︙ | ︙ | |||
1814 1815 1816 1817 1818 1819 1820 | if (readFile != NULL) { /* * Start the background reader thread. */ infoPtr->readable = CreateEventW(NULL, TRUE, TRUE, NULL); infoPtr->readThread = CreateThread(NULL, 256, PipeReaderThread, | | < | < | 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 | if (readFile != NULL) { /* * Start the background reader thread. */ infoPtr->readable = CreateEventW(NULL, TRUE, TRUE, NULL); infoPtr->readThread = CreateThread(NULL, 256, PipeReaderThread, TclPipeThreadCreateTI(&infoPtr->readTI, infoPtr), 0, NULL); SetThreadPriority(infoPtr->readThread, THREAD_PRIORITY_HIGHEST); infoPtr->validMask |= TCL_READABLE; } else { infoPtr->readTI = NULL; infoPtr->readThread = 0; } if (writeFile != NULL) { /* * Start the background writer thread. */ infoPtr->writable = CreateEventW(NULL, TRUE, TRUE, NULL); infoPtr->writeThread = CreateThread(NULL, 256, PipeWriterThread, TclPipeThreadCreateTI(&infoPtr->writeTI, infoPtr), 0, NULL); SetThreadPriority(infoPtr->writeThread, THREAD_PRIORITY_HIGHEST); infoPtr->validMask |= TCL_WRITABLE; } else { infoPtr->writeTI = NULL; infoPtr->writeThread = 0; } |
︙ | ︙ | |||
3297 3298 3299 3300 3301 3302 3303 | * *---------------------------------------------------------------------- */ TclPipeThreadInfo * TclPipeThreadCreateTI( TclPipeThreadInfo **pipeTIPtr, | | < < | 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 | * *---------------------------------------------------------------------- */ TclPipeThreadInfo * TclPipeThreadCreateTI( TclPipeThreadInfo **pipeTIPtr, void *clientData) { TclPipeThreadInfo *pipeTI; #ifndef _PTI_USE_CKALLOC pipeTI = (TclPipeThreadInfo *)malloc(sizeof(TclPipeThreadInfo)); #else pipeTI = (TclPipeThreadInfo *)Tcl_Alloc(sizeof(TclPipeThreadInfo)); #endif /* !_PTI_USE_CKALLOC */ pipeTI->evControl = CreateEventW(NULL, FALSE, FALSE, NULL); pipeTI->state = PTI_STATE_IDLE; pipeTI->clientData = clientData; return (*pipeTIPtr = pipeTI); } /* *---------------------------------------------------------------------- * * TclPipeThreadWaitForSignal -- |
︙ | ︙ | |||
3337 3338 3339 3340 3341 3342 3343 | int TclPipeThreadWaitForSignal( TclPipeThreadInfo **pipeTIPtr) { TclPipeThreadInfo *pipeTI = *pipeTIPtr; LONG state; DWORD waitResult; | < < < | 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 | int TclPipeThreadWaitForSignal( TclPipeThreadInfo **pipeTIPtr) { TclPipeThreadInfo *pipeTI = *pipeTIPtr; LONG state; DWORD waitResult; if (!pipeTI) { return 0; } /* * Wait for the main thread to signal before attempting to do the work. */ /* * Reset work state of thread (idle/waiting) */ |
︙ | ︙ | |||
3404 3405 3406 3407 3408 3409 3410 | end: /* * End of work, check the owner of the TI structure. */ if (state != PTI_STATE_STOP) { *pipeTIPtr = NULL; | < < < < < | 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 | end: /* * End of work, check the owner of the TI structure. */ if (state != PTI_STATE_STOP) { *pipeTIPtr = NULL; } return 0; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
3442 3443 3444 3445 3446 3447 3448 | HANDLE evControl; int state; if (!pipeTI) { return 1; } evControl = pipeTI->evControl; | < | 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 | HANDLE evControl; int state; if (!pipeTI) { return 1; } evControl = pipeTI->evControl; state = InterlockedCompareExchange(&pipeTI->state, PTI_STATE_STOP, PTI_STATE_IDLE); switch (state) { case PTI_STATE_IDLE: /* * Thread was idle/waiting, notify it goes teardown */ |
︙ | ︙ | |||
3506 3507 3508 3509 3510 3511 3512 | int state; if (!pipeTI) { return; } pipeTI = *pipeTIPtr; evControl = pipeTI->evControl; | < | 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 | int state; if (!pipeTI) { return; } pipeTI = *pipeTIPtr; evControl = pipeTI->evControl; /* * Try to sane stop the pipe worker, corresponding its current state */ state = InterlockedCompareExchange(&pipeTI->state, PTI_STATE_STOP, PTI_STATE_IDLE); |
︙ | ︙ | |||
3658 3659 3660 3661 3662 3663 3664 | } } } } *pipeTIPtr = NULL; if (pipeTI) { | < < < | 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 | } } } } *pipeTIPtr = NULL; if (pipeTI) { CloseHandle(pipeTI->evControl); #ifndef _PTI_USE_CKALLOC free(pipeTI); #else Tcl_Free(pipeTI); #endif /* !_PTI_USE_CKALLOC */ } |
︙ | ︙ | |||
3709 3710 3711 3712 3713 3714 3715 | if (!pipeTI) { return; } *pipeTIPtr = NULL; state = InterlockedExchange(&pipeTI->state, PTI_STATE_DOWN); if (state == PTI_STATE_STOP) { CloseHandle(pipeTI->evControl); | < < < | 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 | if (!pipeTI) { return; } *pipeTIPtr = NULL; state = InterlockedExchange(&pipeTI->state, PTI_STATE_DOWN); if (state == PTI_STATE_STOP) { CloseHandle(pipeTI->evControl); #ifndef _PTI_USE_CKALLOC free(pipeTI); #else Tcl_Free(pipeTI); /* be sure all subsystems used are finalized */ Tcl_FinalizeThread(); #endif /* !_PTI_USE_CKALLOC */ |
︙ | ︙ |
Changes to win/tclWinSerial.c.
︙ | ︙ | |||
1502 1503 1504 1505 1506 1507 1508 | /* * Initially the channel is writable and the writeThread is idle. */ infoPtr->osWrite.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); infoPtr->evWritable = CreateEventW(NULL, TRUE, TRUE, NULL); infoPtr->writeThread = CreateThread(NULL, 256, SerialWriterThread, | | < | 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 | /* * Initially the channel is writable and the writeThread is idle. */ infoPtr->osWrite.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); infoPtr->evWritable = CreateEventW(NULL, TRUE, TRUE, NULL); infoPtr->writeThread = CreateThread(NULL, 256, SerialWriterThread, TclPipeThreadCreateTI(&infoPtr->writeTI, infoPtr), 0, NULL); } Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto"); return infoPtr->channel; } |
︙ | ︙ |
Changes to win/tclWinSock.c.
︙ | ︙ | |||
513 514 515 516 517 518 519 | PostMessageW(tsdPtr->hwnd, SOCKET_TERMINATE, 0, 0); /* * Wait for the thread to exit. This ensures that we are * completely cleaned up before we leave this function. */ | | | 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 | PostMessageW(tsdPtr->hwnd, SOCKET_TERMINATE, 0, 0); /* * Wait for the thread to exit. This ensures that we are * completely cleaned up before we leave this function. */ WaitForSingleObject(tsdPtr->socketThread, INFINITE); tsdPtr->hwnd = NULL; } CloseHandle(tsdPtr->socketThread); tsdPtr->socketThread = NULL; } if (tsdPtr->readyEvent != NULL) { CloseHandle(tsdPtr->readyEvent); |
︙ | ︙ | |||
2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 | * place to look for bugs. */ if (bind(sock, addrPtr->ai_addr, (socklen_t)addrPtr->ai_addrlen) == SOCKET_ERROR) { Tcl_WinConvertError((DWORD) WSAGetLastError()); closesocket(sock); continue; } if (port == 0 && chosenport == 0) { address sockname; socklen_t namelen = sizeof(sockname); /* | > | 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 | * place to look for bugs. */ if (bind(sock, addrPtr->ai_addr, (socklen_t)addrPtr->ai_addrlen) == SOCKET_ERROR) { Tcl_WinConvertError((DWORD) WSAGetLastError()); closesocket(sock); sock = INVALID_SOCKET; /* Bug [40b1814b93] */ continue; } if (port == 0 && chosenport == 0) { address sockname; socklen_t namelen = sizeof(sockname); /* |
︙ | ︙ | |||
2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 | if (backlog < 0) { backlog = SOMAXCONN; } if (listen(sock, backlog) == SOCKET_ERROR) { Tcl_WinConvertError((DWORD) WSAGetLastError()); closesocket(sock); continue; } if (statePtr == NULL) { /* * Add this socket to the global list of sockets. */ | > | 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 | if (backlog < 0) { backlog = SOMAXCONN; } if (listen(sock, backlog) == SOCKET_ERROR) { Tcl_WinConvertError((DWORD) WSAGetLastError()); closesocket(sock); sock = INVALID_SOCKET; /* Bug [40b1814b93] */ continue; } if (statePtr == NULL) { /* * Add this socket to the global list of sockets. */ |
︙ | ︙ |