Skip to content

Commit 18f8719

Browse files
committed
Preserve sticky module requirements during purge
Purge skips sticky and super-sticky modules but still attempts to unload their non-sticky requirements. This reports an unrelated dependency error without explaining why the requirement remains loaded. Preserve requirements needed by retained sticky modules and apply the sticky_purge reporting mode to their skipped unload. Fixes #582 Assisted-by: Codex:gpt-5.6-sol Codex:gpt-6-astra Signed-off-by: Adrien Cotte <adrien.cotte@asplus.fr>
1 parent 3e543d9 commit 18f8719

15 files changed

Lines changed: 273 additions & 14 deletions

‎.hunspell.en.dic‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,7 @@ gh
492492
ghcommit
493493
gitlog
494494
gmake
495+
gpt
495496
grp
496497
gz
497498
gzip

‎NEWS.rst‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ Modules 5.7.0 (not yet released)
251251
* Doc: add the :ref:`user-guide` document that explains a selection of
252252
useful but lesser known features through practical examples and common
253253
use cases.
254+
* Keep non-sticky requirements of sticky modules loaded during a
255+
:subcmd:`purge` and explicitly report why their unload is skipped according
256+
to the :mconfig:`sticky_purge` configuration. (fix issue #582)
254257

255258

256259
.. _5.6 release notes:

‎doc/source/changes.rst‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,15 @@ Module Sub-Commands
648648
these variables. Exception is made for :envvar:`MODULEPATH` environment
649649
variable where the mechanism still applies.
650650

651+
:subcmd:`purge`
652+
653+
Starting with version 5.7, direct and indirect requirements of retained
654+
sticky and super-sticky modules are kept loaded, even if those requirements
655+
are not sticky themselves. The :mconfig:`sticky_purge` configuration
656+
controls reporting for their skipped unload as well as for sticky modules.
657+
With :option:`--force`, sticky modules and their requirements can be
658+
unloaded, but super-sticky modules and their requirements remain loaded.
659+
651660
:subcmd:`refresh`
652661

653662
Sub-command evaluates all loaded modulefiles and re-apply the non-persistent

‎doc/source/cookbook/sticky-modules.rst‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,4 +170,40 @@ for load in the initialization RC file |file etcdir_initrc|:
170170
module load core
171171
module load compiler/compB
172172
173+
Preserving requirements during purge
174+
------------------------------------
175+
176+
Starting with Modules v5.7, :subcmd:`purge` also keeps the direct and indirect
177+
requirements of retained sticky or super-sticky modules loaded. These
178+
requirements do not need a sticky tag of their own.
179+
180+
For example, a site may provide a *default_workspace/enterprise* module
181+
tagged *super-sticky*, with the following requirement in its modulefile:
182+
183+
.. code-block:: tcl
184+
185+
prereq workspace/enterprise
186+
187+
To keep this module and its workspace requirement without reporting their
188+
skipped unload, set :mconfig:`sticky_purge` to ``silent``:
189+
190+
.. code-block:: sh
191+
192+
module config sticky_purge silent
193+
module load workspace/partner
194+
module load workspace/enterprise
195+
module load default_workspace/enterprise
196+
module purge
197+
198+
The unrelated *workspace/partner* module is unloaded. Both
199+
*workspace/enterprise* and *default_workspace/enterprise* remain loaded,
200+
without a dependency error. The same applies to ``module purge --force``
201+
because *default_workspace/enterprise* is super-sticky.
202+
203+
With ``sticky_purge`` set to ``warning`` or ``error`` (the default), the
204+
skipped unload of *workspace/enterprise* instead reports ``Unload of
205+
super-sticky module requirement skipped`` at the corresponding severity.
206+
For a module tagged *sticky*, ``--force`` allows both it and its requirements
207+
to be unloaded unless a retained super-sticky module still needs them.
208+
173209
.. vim:set tabstop=2 shiftwidth=2 expandtab autoindent:

‎doc/source/design/evaluation-errors.rst‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,13 @@ In case of error, *continue on error* behavior is applied. If purge is added
336336
in the value list of :mconfig:`abort_on_error` configuration option and if
337337
force mode is not set, *abort on error* behavior applies.
338338

339+
Starting Modules 5.7, unload of a requirement needed by a retained sticky or
340+
super-sticky module is skipped according to :mconfig:`sticky_purge`.
341+
``error`` raises an error and follows the above abort or continue behavior.
342+
``warning`` and ``silent`` skip unload without an error exit code. This also
343+
applies to indirect requirements and, even in force mode, to requirements of
344+
super-sticky modules.
345+
339346
Unload sub-command
340347
------------------
341348

‎doc/source/design/module-tags.rst‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ Specification
5656
- ``super-sticky``: loaded module cannot be unloaded even if forced, it stills can be unloaded if reloaded afterward (see :ref:`sticky-modules`)
5757
- ``keep-loaded``: auto_handling mechanism does not unload auto-loaded module
5858

59+
- Starting Modules 5.7, :subcmd:`purge` also preserves the direct and
60+
indirect requirements of retained ``sticky`` or ``super-sticky`` modules.
61+
Requirements do not inherit these tags. Their unload is skipped according
62+
to :mconfig:`sticky_purge`, including when a requirement has no sticky tag.
63+
With :option:`--force`, only requirements needed by retained super-sticky
64+
modules are protected by this mechanism.
65+
5966
- Tags inherited from module state cannot be set with ``module-tag`` command
6067

6168
- An error is otherwise thrown

‎doc/source/design/sticky-modules.rst‎

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,16 @@ Specification
4848
- it means stickiness applies to the module version
4949
- thus these versions targeted specifically with ``module-tag`` cannot be swapped by another version from same module
5050

51-
- When a super-sticky module depends on a non-super-sticky module
51+
- Starting Modules 5.7, ``purge`` preserves requirements of retained sticky
52+
and super-sticky modules
5253

53-
- If a forced ``purge`` command occurs, the dependent module will be unloaded
54-
- Which let the super-sticky module with a missing dependency
54+
- Direct and indirect requirements are preserved, even without a sticky tag
55+
- Only strong requirements are preserved: an alternative requirement may
56+
be unloaded while another loaded module still satisfies it
57+
- A forced ``purge`` unloads sticky modules and can unload their
58+
requirements, but preserves super-sticky modules and their requirements
59+
- Before version 5.7, a forced ``purge`` could unload a non-super-sticky
60+
requirement and leave a super-sticky module with a missing dependency
5561

5662
- Starting Modules 5.2, sticky modules are unloaded
5763

@@ -88,6 +94,13 @@ Specification
8894
code
8995
- when set to ``silent``, no message reported, no error exit code
9096

97+
- Starting Modules 5.7, this configuration also applies to skipped unload
98+
of requirements of retained sticky or super-sticky modules
99+
- Requirement unload is reported as ``Unload of sticky module requirement
100+
skipped`` or ``Unload of super-sticky module requirement skipped``
101+
- If both sticky and super-sticky modules require a module, the
102+
super-sticky tag takes precedence in this message
103+
91104
- Even when ``sticky_purge`` is set to ``silent``, a warning message is
92105
reported when unload of sticky module is forced during a purge.
93106

‎doc/source/module.rst‎

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,8 @@ switches are accepted:
341341
On :subcmd:`clear` sub-command, skip the confirmation dialog and proceed.
342342

343343
On :subcmd:`purge` sub-command also unload `sticky modules`_ and modulefiles
344-
that are depended by non-unloadable modules.
344+
that are depended by non-unloadable modules, except requirements of retained
345+
super-sticky modules.
345346

346347
.. only:: html or latex
347348

@@ -1772,6 +1773,9 @@ Module Sub-Commands
17721773
Error behavior when unloading sticky or super-sticky module during a module
17731774
:subcmd:`purge`.
17741775

1776+
Also applies to modules whose unload is skipped because they are required,
1777+
directly or indirectly, by a retained sticky or super-sticky module.
1778+
17751779
Raise an ``error`` (default) or emit a ``warning`` or be ``silent``. It can
17761780
be changed at installation time with :instopt:`--with-sticky-purge` option.
17771781
The :envvar:`MODULES_STICKY_PURGE` environment variable is defined by
@@ -2379,9 +2383,15 @@ Module Sub-Commands
23792383

23802384
Unload all loaded *modulefiles*.
23812385

2386+
Sticky and super-sticky modules are kept loaded, along with their required
2387+
modules, including indirect requirements. Unload attempts for these modules
2388+
are skipped according to the :mconfig:`sticky_purge` configuration: raise an
2389+
``error`` (default), emit a ``warning`` or remain ``silent``.
2390+
23822391
When the :option:`--force` option is set, also unload `sticky modules`_,
23832392
modulefiles that are depended by non-unloadable modules and modulefiles
2384-
raising an evaluation error.
2393+
raising an evaluation error. Super-sticky modules and their requirements
2394+
remain loaded even with :option:`--force`.
23852395

23862396
If one modulefile unload evaluation raises an error, purge sequence
23872397
continues: unloaded modules prior the evaluation error are kept unloaded and
@@ -2398,6 +2408,9 @@ Module Sub-Commands
23982408
.. versionchanged:: 5.4
23992409
Support for :mconfig:`abort_on_error` configuration option added
24002410

2411+
.. versionchanged:: 5.7
2412+
Preserve requirements of retained sticky and super-sticky modules
2413+
24012414
.. subcmd:: refresh
24022415

24032416
Force a refresh of all non-persistent components of currently loaded modules.
@@ -3542,6 +3555,14 @@ Modules are designated sticky by associating them the ``sticky`` or the
35423555
``super-sticky`` :ref:`module tag<Module tags>` with the :mfcmd:`module-tag`
35433556
modulefile command.
35443557

3558+
Starting with version 5.7, :subcmd:`purge` also preserves the direct and
3559+
indirect requirements of retained sticky or super-sticky modules, even if
3560+
these requirements have no sticky tag. The :mconfig:`sticky_purge`
3561+
configuration applies to their skipped unload. With :option:`--force`,
3562+
sticky modules can be unloaded, but super-sticky modules and their
3563+
requirements remain loaded. If several loaded modules satisfy an alternative
3564+
requirement, only the last necessary one is preserved.
3565+
35453566
When stickiness is defined over the generic module name (and not over a
35463567
specific module version, a version list or a version range), sticky or
35473568
super-sticky module can be swapped by another version of module. For instance
@@ -6128,6 +6149,9 @@ ENVIRONMENT
61286149
:subcmd:`purge`, raise an ``error`` or emit a ``warning`` message or be
61296150
``silent``.
61306151

6152+
Also applies to the skipped unload of modules required, directly or
6153+
indirectly, by a retained sticky or super-sticky module.
6154+
61316155
This environment variable value supersedes the default value set in the
61326156
:mconfig:`sticky_purge` configuration option. It can be defined with the
61336157
:subcmd:`config` sub-command.
@@ -6433,4 +6457,3 @@ SEE ALSO
64336457
--------
64346458

64356459
:ref:`envml(1)`, :ref:`ml(1)`, :ref:`modulecmd(1)`, :ref:`modulefile(5)`
6436-

‎tcl/modeval.tcl‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,19 @@ proc isModuleSticky {mod} {
959959
$mod sticky 1] && ![getState force])}]
960960
}
961961

962+
proc getModuleStickyDependentTag {mod} {
963+
set sticky_tag {}
964+
foreach dep_mod [getDependentLoadedModuleList [list $mod] 1 0 0 0] {
965+
if {[isModuleTagged $dep_mod super-sticky 1]} {
966+
set sticky_tag super-sticky
967+
break
968+
} elseif {![getState force] && [isModuleTagged $dep_mod sticky 1]} {
969+
set sticky_tag sticky
970+
}
971+
}
972+
return $sticky_tag
973+
}
974+
962975
proc saveLoadedReqOfUnloadingModule {unload_mod} {
963976
# fetch requirements of unloading module
964977
set ::g_savedLoReqOfUnloadMod($unload_mod)\
@@ -1172,6 +1185,21 @@ proc failOrSkipUnloadIfSticky {modname modfile} {
11721185
return 0
11731186
}
11741187

1188+
proc failOrSkipUnloadIfRequiredBySticky {mod} {
1189+
set sticky_tag [getModuleStickyDependentTag $mod]
1190+
if {$sticky_tag eq {}} {
1191+
return 0
1192+
}
1193+
1194+
set msg [getStickyReqUnloadMsg $sticky_tag]
1195+
switch -- [getConf sticky_purge] {
1196+
error {knerror $msg}
1197+
warning {reportWarning $msg}
1198+
}
1199+
1200+
return 1
1201+
}
1202+
11751203
# ;;; Local Variables:
11761204
# ;;; Mode: tcl-mode
11771205
# ;;; tcl-indent-level: 3

‎tcl/report.tcl.in‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,6 +1115,10 @@ proc getStickyUnloadMsg {{tag sticky}} {
11151115
return "Unload of $tag module skipped"
11161116
}
11171117
1118+
proc getStickyReqUnloadMsg {{tag sticky}} {
1119+
return "Unload of $tag module requirement skipped"
1120+
}
1121+
11181122
proc getStickyForcedUnloadMsg {} {
11191123
return {Unload of sticky module forced}
11201124
}

0 commit comments

Comments
 (0)