19081: Disable singularity env var eval behavior if possible.
[arvados.git] / lib / crunchrun / singularity.go
index 942de4300e087a95306fc2de1d20288535581a67..61992b312dac8cf3f0757523419b771bf4e6b34e 100644 (file)
@@ -10,7 +10,6 @@ import (
        "os"
        "os/exec"
        "sort"
-       "strings"
        "syscall"
        "time"
 
@@ -288,11 +287,19 @@ func (e *singularityExecutor) execCmd(path string) *exec.Cmd {
        // Singularity always makes all nvidia devices visible to the
        // container.  If a resource manager such as slurm or LSF told
        // us to select specific devices we need to propagate that.
-       for _, s := range os.Environ() {
-               if strings.HasPrefix(s, "CUDA_VISIBLE_DEVICES=") {
-                       env = append(env, "SINGULARITYENV_"+s)
-               }
+       if cudaVisibleDevices := os.Getenv("CUDA_VISIBLE_DEVICES"); cudaVisibleDevices != "" {
+               // If a resource manager such as slurm or LSF told
+               // us to select specific devices we need to propagate that.
+               env = append(env, "SINGULARITYENV_CUDA_VISIBLE_DEVICES="+cudaVisibleDevices)
        }
+       // Singularity's default behavior is to evaluate each
+       // SINGULARITYENV_* env var with a shell as a double-quoted
+       // string and pass the result to the contained
+       // process. Singularity 3.10+ has an option to pass env vars
+       // through literally without evaluating, which is what we
+       // want. See https://github.com/sylabs/singularity/pull/704
+       // and https://dev.arvados.org/issues/19081
+       env = append(env, "SINGULARITY_NO_EVAL=1")
 
        args = append(args, e.imageFilename)
        args = append(args, e.spec.Command...)