diff --git a/lib/galaxy/config/sample/job_conf.xml.sample_advanced b/lib/galaxy/config/sample/job_conf.xml.sample_advanced index dc67a4763d74..0ae9c855d3be 100644 --- a/lib/galaxy/config/sample/job_conf.xml.sample_advanced +++ b/lib/galaxy/config/sample/job_conf.xml.sample_advanced @@ -604,6 +604,12 @@ true + + true + + + + diff --git a/lib/galaxy/tool_util/deps/container_classes.py b/lib/galaxy/tool_util/deps/container_classes.py index 769729f6bf9e..e00c005e5275 100644 --- a/lib/galaxy/tool_util/deps/container_classes.py +++ b/lib/galaxy/tool_util/deps/container_classes.py @@ -573,6 +573,8 @@ def containerize_command(self, command: str) -> str: guest_ports=self.tool_info.guest_ports, container_name=self.container_name, cleanenv=asbool(self.prop("cleanenv", singularity_util.DEFAULT_CLEANENV)), + ipc=asbool(self.prop("ipc", singularity_util.DEFAULT_IPC)), + pid=asbool(self.prop("pid", singularity_util.DEFAULT_PID)), no_mount=self.prop("no_mount", singularity_util.DEFAULT_NO_MOUNT), **self.get_singularity_target_kwds(), ) diff --git a/lib/galaxy/tool_util/deps/singularity_util.py b/lib/galaxy/tool_util/deps/singularity_util.py index 6d0044aa8cf1..081c706fc3c4 100644 --- a/lib/galaxy/tool_util/deps/singularity_util.py +++ b/lib/galaxy/tool_util/deps/singularity_util.py @@ -13,7 +13,12 @@ DEFAULT_WORKING_DIRECTORY = None DEFAULT_SINGULARITY_COMMAND = "singularity" +# --pid isolates the pid namespace. --ipc isolates +# the ipc namespace, this fixes some issues with python multiprocessing. +# --cleanenv makes sure the current environment is not inherited. DEFAULT_CLEANENV = True +DEFAULT_IPC = True +DEFAULT_PID = True DEFAULT_NO_MOUNT = ["tmp"] DEFAULT_SUDO = False DEFAULT_SUDO_COMMAND = "sudo" @@ -71,6 +76,8 @@ def build_singularity_run_command( guest_ports: Union[bool, List[str]] = False, container_name: Optional[str] = None, cleanenv: bool = DEFAULT_CLEANENV, + ipc: bool = DEFAULT_IPC, + pid: bool = DEFAULT_PID, no_mount: Optional[List[str]] = DEFAULT_NO_MOUNT, ) -> str: volumes = volumes or [] @@ -89,8 +96,19 @@ def build_singularity_run_command( ) command_parts.append("-s") command_parts.append("exec") + # Singularity mounts some directories, such as $HOME and $PWD by default. + # using --contain disables this behaviour and only allows explicitly + # requested volumes to be mounted. This gives fully full-control over + # the mounting behavior. + command_parts.append("--contain") + if working_directory: + command_parts.extend(["--pwd", shlex.quote(working_directory)]) if cleanenv: command_parts.append("--cleanenv") + if ipc: + command_parts.append("--ipc") + if pid: + command_parts.append("--pid") if no_mount: command_parts.extend(["--no-mount", ",".join(no_mount)]) for volume in volumes: diff --git a/test/unit/tool_util/test_singularity_util.py b/test/unit/tool_util/test_singularity_util.py index 2399a70a91b6..dc460285f520 100644 --- a/test/unit/tool_util/test_singularity_util.py +++ b/test/unit/tool_util/test_singularity_util.py @@ -6,13 +6,15 @@ def test_build_singularity_run_command_defaults(): container_command="echo hi", image="busybox", ) - assert cmd == "singularity -s exec --cleanenv --no-mount tmp busybox echo hi" + assert cmd == "singularity -s exec --contain --cleanenv --ipc --pid --no-mount tmp busybox echo hi" -def test_build_singularity_run_command_no_cleanenv(): +def test_build_singularity_run_command_no_cleanenv_ipc_pid(): cmd = build_singularity_run_command( container_command="echo hi", image="busybox", cleanenv=False, + pid=False, + ipc=False, ) - assert cmd == "singularity -s exec --no-mount tmp busybox echo hi" + assert cmd == "singularity -s exec --contain --no-mount tmp busybox echo hi"