Repository: ESMCI/cime

Issue:
Deaths from perl-based build-namelists are silently suppressed
I noticed that `die` statements from perl-based build-namelists are being suppressed: their error message isn't printed, and the overall preview_namelists process simply moves on to the next component. This can lead to the given component's namelist file not being written at all, or - worse - it can be written incorrectly.

In CESM, here is a simple case that demonstrates the problem; you could probably come up with something similar in ACME:

With these diffs in components/cism/bld/build-namelist, off of the cesm2_0_alpha07d sandbox (also true in alpha07c):

```diff
Index: bld/build-namelist
===================================================================
--- bld/build-namelist	(revision 86564)
+++ bld/build-namelist	(working copy)
@@ -56,6 +56,10 @@
 EOF
 }

+print "I am about to die\n";
+die "a horrible death\n";
+print "I have been resurrected!\n";
+
 #-----------------------------------------------------------------------------------------------
 # Set some important constants, such as important values of certain config file parameters
```

I ran

```
./create_newcase --case test_die_0906a --compset T1850G --res f09_g16 --run-unsupported
cd test_die_0906a/
./case.setup
./preview_namelists
```

and got

```
Creating component namelists
   Calling /glade2/scratch2/sacks/cesm_code/cesm2_0_alpha07/cime/src/components/stub_comps/satm/cime_config/buildnml
   Calling /glade2/scratch2/sacks/cesm_code/cesm2_0_alpha07/cime/src/components/data_comps/dlnd/cime_config/buildnml
   Calling /glade2/scratch2/sacks/cesm_code/cesm2_0_alpha07/cime/src/components/stub_comps/sice/cime_config/buildnml
   Calling /glade2/scratch2/sacks/cesm_code/cesm2_0_alpha07/cime/src/components/stub_comps/socn/cime_config/buildnml
   Calling /glade2/scratch2/sacks/cesm_code/cesm2_0_alpha07/cime/src/components/stub_comps/srof/cime_config/buildnml
   Running /glade2/scratch2/sacks/cesm_code/cesm2_0_alpha07/components/cism/cime_config/buildnml
I am about to die
   Calling /glade2/scratch2/sacks/cesm_code/cesm2_0_alpha07/cime/src/components/stub_comps/swav/cime_config/buildnml
   Calling /glade2/scratch2/sacks/cesm_code/cesm2_0_alpha07/cime/src/components/stub_comps/sesp/cime_config/buildnml
   Calling /glade2/scratch2/sacks/cesm_code/cesm2_0_alpha07/cime/src/drivers/mct/cime_config/buildnml
Finished creating component namelists
```

No cism namelist file was created.

cc @mvertens @jedwards4b @fischer-ncar @jgfouca @rljacob 


Discussion:

Resolving patch:
diff --git a/scripts/lib/CIME/preview_namelists.py b/scripts/lib/CIME/preview_namelists.py
--- a/scripts/lib/CIME/preview_namelists.py
+++ b/scripts/lib/CIME/preview_namelists.py
@@ -85,7 +85,8 @@ def create_namelists(case, component=None):
                 # otherwise look in the component config_dir
                 cmd = os.path.join(config_dir, "buildnml")
             expect(os.path.isfile(cmd), "Could not find buildnml file for component {}".format(compname))
-            run_sub_or_cmd(cmd, (caseroot), "buildnml", (case, caseroot, compname), case=case)
+            run_sub_or_cmd(cmd, (caseroot), "buildnml", (case, caseroot, compname), case=case,
+                           combine_output=True)
 
     logger.info("Finished creating component namelists")
 
diff --git a/scripts/lib/CIME/utils.py b/scripts/lib/CIME/utils.py
--- a/scripts/lib/CIME/utils.py
+++ b/scripts/lib/CIME/utils.py
@@ -199,8 +199,7 @@ def _convert_to_fd(filearg, from_dir):
 _hack=object()
 
 def run_sub_or_cmd(cmd, cmdargs, subname, subargs, logfile=None, case=None,
-                   input_str=None, from_dir=None, verbose=None,
-                   arg_stdout=_hack, arg_stderr=_hack, env=None, combine_output=False):
+                   from_dir=None, combine_output=False):
 
     # This code will try to import and run each buildnml as a subroutine
     # if that fails it will run it as a program in a seperate shell
@@ -227,10 +226,8 @@ def run_sub_or_cmd(cmd, cmdargs, subname, subargs, logfile=None, case=None,
         logger.info("   Running {} ".format(cmd))
         if case is not None:
             case.flush()
-        stat, output, errput = run_cmd("{} {}".format(cmd, cmdargs), input_str=input_str, from_dir=from_dir,
-                                 verbose=verbose, arg_stdout=arg_stdout, arg_stderr=arg_stderr, env=env,
-                                 combine_output=combine_output)
-
+        output = run_cmd_no_fail("{} {}".format(cmd, cmdargs), combine_output=combine_output,
+                                 from_dir=from_dir)
         logger.info(output)
         # refresh case xml object from file
         if case is not None:


Test patch: