Skip to content

Commit

Permalink
Check stickiness prior processing dependent unload
Browse files Browse the repository at this point in the history
Move stickiness check when unloading a module prior processing any
automated module handling mechanism.

Stickiness check procedure is renamed failOrSkipUnloadIfSticky and moved
from interp.tcl to modeval.tcl file.

Fixes #536
  • Loading branch information
xdelaruelle committed Oct 27, 2024
1 parent f7994a4 commit d826c11
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 50 deletions.
2 changes: 2 additions & 0 deletions NEWS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ Modules 5.5.0 (not yet released)
when trying to reload Dependent Reload modules that conflict with other
loaded modules. This error may be by-passed with :option:`--force`
command-line option.
* Move stickiness check when unloading a module prior processing any automated
module handling mechanism. (fix issue #536)

.. warning:: Variant names are now fully checked instead of just verifying
their first character. Only characters within the ``A-Za-z0-9_-`` range are
Expand Down
50 changes: 0 additions & 50 deletions tcl/interp.tcl.in
Original file line number Diff line number Diff line change
Expand Up @@ -184,50 +184,6 @@ x-resource {x-resource x-resource reportCmd nop nop
}
}

# Fail unload attempt if module is sticky, unless if forced or reloading
# Also fail unload if mod is super-sticky even if forced, unless reloading
proc skipUnloadIfSticky {mode modname modfile} {
if {$mode ne {unload}} {
return 0
}

# when loaded, tags applies to mod name and version (not with variant)
set is_supersticky_not_reloading [expr {[isModuleTagged $modname\
super-sticky 1 $modfile] && [currentState reloading_supersticky] ne\
$modname}]
set is_sticky_not_reloading [expr {[isModuleTagged $modname sticky 1\
$modfile] && [currentState reloading_sticky] ne $modname &&\
[currentState unloading_sticky] ne $modname}]
set sticky_purge [expr {[getState commandname] eq {purge} ? [getConf\
sticky_purge] : {}}]

if {!$is_supersticky_not_reloading && $is_sticky_not_reloading &&\
[getState force]} {
reportWarning [getStickyForcedUnloadMsg]
} elseif {$is_supersticky_not_reloading || $is_sticky_not_reloading} {
# restore changed states prior raising error
lpopState debug_msg_prefix
lpopState modulepath
lpopState specifiedname
lpopState modulename
lpopState modulenamevr
lpopState modulefile

set msg [getStickyUnloadMsg [expr {$is_supersticky_not_reloading ?\
{super-sticky} : {sticky}}]]
# no message if sticky_purge is set to silent
switch -- $sticky_purge {
error - {} {knerror $msg}
warning {reportWarning $msg}
}

# skip unload without raised error
return 1
}

return 0
}

proc execute-modulefile {modfile modname modnamevrvar modspec requested\
{up_namevr 1} {fetch_tags 1} {modpath {}}} {
# link to modnamevr variable name from calling ctx if content update asked
Expand Down Expand Up @@ -267,12 +223,6 @@ proc execute-modulefile {modfile modname modnamevrvar modspec requested\
set nearlyforbidwarn 1
}

# fail unload when sticky
if {[skipUnloadIfSticky $mode $modname $modfile]} {
# skip end of unload upper level process when no error raised
return -code continue 0
}

if {![info exists ::g_modfileUntrackVars]} {
# list variable that should not be tracked for saving
array set ::g_modfileUntrackVars [list ModulesCurrentModulefile 1 env 1]
Expand Down
32 changes: 32 additions & 0 deletions tcl/modeval.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,38 @@ proc reloadDepReModules {} {
reloadModuleListLoadPhase $depre_list $err_msg_tpl depre
}

# Fail unload attempt if module is sticky, unless if forced or reloading
# Also fail unload if mod is super-sticky even if forced, unless reloading
proc failOrSkipUnloadIfSticky {modname modfile} {
# when loaded, tags applies to mod name and version (not with variant)
set is_supersticky_not_reloading [expr {[isModuleTagged $modname\
super-sticky 1 $modfile] && [currentState reloading_supersticky] ne\
$modname}]
set is_sticky_not_reloading [expr {[isModuleTagged $modname sticky 1\
$modfile] && [currentState reloading_sticky] ne $modname &&\
[currentState unloading_sticky] ne $modname}]
set sticky_purge [expr {[getState commandname] eq {purge} ? [getConf\
sticky_purge] : {}}]

if {!$is_supersticky_not_reloading && $is_sticky_not_reloading &&\
[getState force]} {
reportWarning [getStickyForcedUnloadMsg]
} elseif {$is_supersticky_not_reloading || $is_sticky_not_reloading} {
set msg [getStickyUnloadMsg [expr {$is_supersticky_not_reloading ?\
{super-sticky} : {sticky}}]]
# no message if sticky_purge is set to silent
switch -- $sticky_purge {
error - {} {knerror $msg}
warning {reportWarning $msg}
}

# skip unload without raising error
return 1
}

return 0
}

# ;;; Local Variables: ***
# ;;; mode:tcl ***
# ;;; End: ***
Expand Down
4 changes: 4 additions & 0 deletions tcl/subcmd.tcl.in
Original file line number Diff line number Diff line change
Expand Up @@ -1546,6 +1546,10 @@ proc cmdModuleUnload {context match auto force onlyureq args} {

pushSettings
if {[set errCode [catch {
if {[failOrSkipUnloadIfSticky $modname $modfile]} {
continue
}

# stop unless forced or auto handling mode enabled if unloading
# module violates a registered prereq
set prereq_list [getDependentLoadedModuleList [list $modname]]
Expand Down

0 comments on commit d826c11

Please sign in to comment.