@ -7,7 +7,7 @@
# (C) 2025
#
# @@ Meta Begin
# Application punk::libunknown 0.2.1
# Application punk::libunknown 0.2.2
# Meta platform tcl
# Meta license MIT
# @@ Meta End
@ -18,6 +18,19 @@
# from src/modules/AGENTS.md "Versioning And Releases" - bumping means
# renaming the file AND updating the Meta line above, the manpage_begin line
# below and the provide-block version, then appending a line here):
#0.2.2 - zipfs_tm_UnknownHandler: the builtin-static shortcircuit probe interp no
# longer leaks (G-120). The probe child interp was created under the fixed
# name ptest and deleted only on the non-error paths; an unversioned
# 'package require foo' of a static package made the version check
# 'package vsatisfies $v' throw (wrong # args - vsatisfies needs >=1
# requirement), skipping the delete. The leaked child held registrations
# on the process std channels (Tcl shares them into non-safe child
# interps), so an explicit 'chan close stderr' left the OS handle alive
# and the std slot occupied - the next opened channel got a fileN name
# instead of recycling into stderr. Now: auto-named probe interp, deleted
# in a try/finally; zero-requirement requires treat any provided version
# as satisfying; probe errors fall through to the normal tm search
# instead of aborting the require.
#0.2.1 - zipfs_tm_UnknownHandler: the zipfs static-path can_skip_update state is
# written keyed by the SPECIFIC searchpath actually scanned (tm path +
# package namespace subdir) to match its reader and libunknown::init's
@ -42,7 +55,7 @@
# doctools header
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[manpage_begin punkshell_module_punk::libunknown 0 0.2.1 ]
#[manpage_begin punkshell_module_punk::libunknown 0 0.2.2 ]
#[copyright "2025"]
#[titledesc {Module API}] [comment {-- Name section and table of contents description --}]
#[moddesc {-}] [comment {-- Description at end of page heading --}]
@ -190,22 +203,36 @@ tcl::namespace::eval ::punk::libunknown {
set loaded [lsearch -inline -index 1 -nocase [info loaded] $name]
if {[llength $loaded] == 2 && [lindex $loaded 0] eq ""} {
lassign $loaded _ cased_name
interp create ptest
ptest eval [list load {} $cased_name]
set static_version [ptest eval [list package provide [string tolower $cased_name]]]
set pname [string tolower $cased_name]
if {$static_version eq ""} {
set static_version [ptest eval [list package provide $cased_name]]
set pname $cased_name
}
if {$static_version ne ""} {
if {[package vsatisfies $static_version {*}$args]} {
package ifneeded $pname $static_version [list load {} $cased_name]
interp delete ptest
return
#Version-probe the static package in a throwaway child interp.
#The child must never outlive this block: a (non-safe) child interp
#holds registrations on the process std channels, so a leaked probe
#interp disables Tcl's std-slot recycling process-wide (after
#'chan close stderr' the OS handle stays alive and the slot stays
#occupied, so the next opened channel cannot become stderr) - G-120.
set probeinterp [interp create]
try {
interp eval $probeinterp [list load {} $cased_name]
set static_version [interp eval $probeinterp [list package provide [string tolower $cased_name]]]
set pname [string tolower $cased_name]
if {$static_version eq ""} {
set static_version [interp eval $probeinterp [list package provide $cased_name]]
set pname $cased_name
}
if {$static_version ne ""} {
#zero requirements (plain 'package require foo') accepts any
#provided version; package vsatisfies errors without at least
#one requirement argument.
if {![llength $args] || [package vsatisfies $static_version {*}$args]} {
package ifneeded $pname $static_version [list load {} $cased_name]
return
}
}
} on error {} {
#probe failure (e.g a static whose init needs more than a bare
#child interp) - not fatal: fall through to the normal tm search.
} finally {
interp delete $probeinterp
}
interp delete ptest
}
#------------------------------
@ -2130,7 +2157,7 @@ namespace eval ::punk::args::register {
package provide punk::libunknown [tcl::namespace::eval ::punk::libunknown {
variable pkg punk::libunknown
variable version
set version 0.2.1
set version 0.2.2
}]
return