Repository: easybuilders/easybuild-framework

Issue:
Minor issue with backward compatibility of v1.1.x vs v1.0.2
Hi there,

`There will be no further v1.0.x updates, as v1.1.x should be fully backwards compatible.`

Well, SHOULD ;-)

I will spare you the details the important information is:
- v1.1.0 does apparently a module purge at some point; that interacts badly with our environment because we provide easybuild itself as a module (name: _easybuild_); that module purge will then cause a `which eb` operation to fail; could we perhaps made it default to somehow not purge it? or skip that test alltogether!
- But, why does it actually run OK in interactive mode? that's really not-obvious...
- The information visible below is a bit cryptic, when the stack-trace is not fully visible; is there some guiding logic about when we can see the stack-trace? (it's optimal if we always expose it whenever things break and the code exits).

```
Begin forwarded message:
From: Nils Christian
Date: 30 January 2013 11:42:12 AM GMT+01:00
Subject: problem with easybuild 1.1.0: cmd "which eb" exited with exitcode 1

Hi Fotis,

using easybuild 1.1.0 I ran into a problem using the non-interactive
mode of our queuing system. Attached is the script that that I ran like
this:
oarsub -S ./libyamlbuild-1.1.0

Attached are also the output files. eb fails with

== 2013-01-30 11:36:39,443 main.fileTools ERROR EasyBuild crashed with an error (at easybuild/1.1.0/easybuild-framework/easybuild/tools/filetools.py:601 in parse_cmd_output): cmd "which eb" exited with exitcode 1 and output:


Running an interactive job with 'oarsub -I' and then 'source'-ing the
script works fine. easybuild 1.0.2 works in non-interactive mode, so
something must have changed in 1.1.0 .

Any ideas?

Best
 Nils
```

The interesting part when run in interactive mode:

```
output of 'which eb': /opt/apps/default/software/easybuild/1.1.0/easybuild-framework/eb
== 2013-01-30 11:36:38,310 main.main INFO Log initialized with name None version None to file None on host gaia-14
== 2013-01-30 11:36:38,310 main.main INFO This is EasyBuild 1.1.0-rab4831712b0bb2d0f02af80fb06a317a3253b2c3 (framework: 1.1.0-rab4831712b0bb2d0f02af80fb06a317a3253b2c3, easyblocks: 1.1.0-r9753576a2f72d3b3e137b0f9026710cc0d21772d)
== 2013-01-30 11:36:38,310 main.fileTools DEBUG run_cmd: running cmd which eb (in /mnt/nfs/users/workdirs/nchristian)
== 2013-01-30 11:36:39,443 main.fileTools ERROR EasyBuild crashed with an error (at easybuild/1.1.0/easybuild-framework/easybuild/tools/filetools.py:601 in parse_cmd_output): cmd "which eb" exited with exitcode 1 and output:
```



Discussion:
EasyBuild v1.1.0 does indeed run a `module purge`, but then restores the environment like it was before it started loading modules itself.
So, even if you had an EasyBuild module loaded, it shouldn't break because of the `module purge` that EasyBuild runs.

Can you run the same command with a full debug log (`-ld`), and provide it?

The environment is not fully restored after a purge and load/unload of fake module.

This issue is caused by 4b13412a836fb47dedbb8ee0b782cfdba3433a06, which should be reverted.


Resolving patch:
diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py
--- a/easybuild/framework/easyblock.py
+++ b/easybuild/framework/easyblock.py
@@ -753,7 +753,7 @@ def load_fake_module(self, purge=False):
         Create and load fake module.
         """
 
-        # take a copy of the environment before loading the fake module
+        # take a copy of the environment before loading the fake module, so we can restore it
         orig_env = copy.deepcopy(os.environ)
 
         # make fake module
@@ -797,13 +797,8 @@ def clean_up_fake_module(self, fake_mod_data):
             except OSError, err:
                 self.log.error("Failed to clean up fake module dir: %s" % err)
 
-        # restore env vars that were set before loading the fake module,
-        # but were unset after unloading it because the module also sets them
-        curr_env = copy.deepcopy(os.environ)
-        for (var, val) in orig_env.items():
-            if not var in curr_env:
-                os.environ[var] = val
-                self.log.debug("Restored value %s for %s that was unset by unloading fake module." % (val, var))
+        # restore original environment
+        modify_env(os.environ, orig_env)
 
     #
     # EXTENSIONS UTILITY FUNCTIONS


Test patch: