[llvm] Reapply "[lit] Implement builtin umask (#94621)" (PR #155850)
    Aiden Grossman via llvm-commits 
    llvm-commits at lists.llvm.org
       
    Thu Aug 28 08:07:17 PDT 2025
    
    
  
https://github.com/boomanaiden154 created https://github.com/llvm/llvm-project/pull/155850
This reverts commit faa4e35c622c13c7a565b979a6676d6cf3040cd4.
This was originally reverted because it was using a Python 3.9 feature (umask in subprocess.Popen) when LLVM only requires Python 3.8. This patch uses os.umask instead, which has been around for longer.
>From c621d9ef89358a91d3db12ad092c411e98633d3e Mon Sep 17 00:00:00 2001
From: Aiden Grossman <aidengrossman at google.com>
Date: Thu, 28 Aug 2025 14:29:15 +0000
Subject: [PATCH] Reapply "[lit] Implement builtin umask (#94621)"
This reverts commit faa4e35c622c13c7a565b979a6676d6cf3040cd4.
This was originally reverted because it was using a Python 3.9 feature
(umask in subprocess.Popen) when LLVM only requires Python 3.8. This
patch uses os.umask instead, which has been around for longer.
---
 .../ELF/X86/mirror-permissions-unix.test      |  1 -
 .../ELF/mirror-permissions-unix.test          |  1 -
 .../tools/llvm-objcopy/ELF/respect-umask.test |  4 +--
 llvm/utils/lit/lit/TestRunner.py              | 29 +++++++++++++++++--
 .../lit/tests/Inputs/shtest-umask/lit.cfg     |  7 +++++
 .../Inputs/shtest-umask/umask-bad-arg.txt     |  1 +
 .../tests/Inputs/shtest-umask/umask-ok.txt    | 11 +++++++
 .../shtest-umask/umask-too-many-args.txt      |  1 +
 llvm/utils/lit/tests/shtest-umask.py          | 18 ++++++++++++
 9 files changed, 66 insertions(+), 7 deletions(-)
 create mode 100644 llvm/utils/lit/tests/Inputs/shtest-umask/lit.cfg
 create mode 100644 llvm/utils/lit/tests/Inputs/shtest-umask/umask-bad-arg.txt
 create mode 100644 llvm/utils/lit/tests/Inputs/shtest-umask/umask-ok.txt
 create mode 100644 llvm/utils/lit/tests/Inputs/shtest-umask/umask-too-many-args.txt
 create mode 100644 llvm/utils/lit/tests/shtest-umask.py
diff --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
index a95d1c0aafa21..fdcba4dcd666b 100644
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
@@ -3,7 +3,6 @@
 ## Setting the umask to 0 ensures deterministic permissions across
 ## test environments.
 # UNSUPPORTED: system-windows
-# REQUIRES: shell
 
 # RUN: touch %t
 # RUN: chmod 0777 %t
diff --git a/llvm/test/tools/llvm-objcopy/ELF/mirror-permissions-unix.test b/llvm/test/tools/llvm-objcopy/ELF/mirror-permissions-unix.test
index 8f4993f4f3d29..66a481a2230d1 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/mirror-permissions-unix.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/mirror-permissions-unix.test
@@ -6,7 +6,6 @@
 ## Setting the umask to 0 ensures deterministic permissions across
 ## test environments.
 # UNSUPPORTED: system-windows
-# REQUIRES: shell
 
 # RUN: touch %t
 # RUN: chmod 0777 %t
diff --git a/llvm/test/tools/llvm-objcopy/ELF/respect-umask.test b/llvm/test/tools/llvm-objcopy/ELF/respect-umask.test
index 376e33a217819..02e9b93f5376f 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/respect-umask.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/respect-umask.test
@@ -1,10 +1,8 @@
 ## This tests that the umask is respected when
 ## assigning permissions of output files.
 
-## Windows has no umask so this test makes no sense, nor would
-## it work because there is no umask(1) in a Windows environment
+## Windows has no umask so this test makes no sense.
 # UNSUPPORTED: system-windows
-# REQUIRES: shell
 
 # RUN: rm -f %t
 # RUN: touch %t
diff --git a/llvm/utils/lit/lit/TestRunner.py b/llvm/utils/lit/lit/TestRunner.py
index 31e3ed679d431..36c19c1c86c75 100644
--- a/llvm/utils/lit/lit/TestRunner.py
+++ b/llvm/utils/lit/lit/TestRunner.py
@@ -98,9 +98,10 @@ class ShellEnvironment(object):
     we maintain a dir stack for pushd/popd.
     """
 
-    def __init__(self, cwd, env):
+    def __init__(self, cwd, env, umask=-1):
         self.cwd = cwd
         self.env = dict(env)
+        self.umask = umask
         self.dirStack = []
 
     def change_dir(self, newdir):
@@ -582,6 +583,20 @@ class SHFILEOPSTRUCTW(Structure):
     return ShellCommandResult(cmd, "", stderr.getvalue(), exitCode, False)
 
 
+def executeBuiltinUmask(cmd, shenv):
+    """executeBuiltinUmask - Change the current umask."""
+    if os.name != "posix":
+        raise InternalShellError(cmd, "'umask' not supported on this system")
+    if len(cmd.args) != 2:
+        raise InternalShellError(cmd, "'umask' supports only one argument")
+    try:
+        # Update the umask in the parent environment.
+        shenv.umask = int(cmd.args[1], 8)
+    except ValueError as err:
+        raise InternalShellError(cmd, "Error: 'umask': %s" % str(err))
+    return ShellCommandResult(cmd, "", "", 0, False)
+
+
 def executeBuiltinColon(cmd, cmd_shenv):
     """executeBuiltinColon - Discard arguments and exit with status 0."""
     return ShellCommandResult(cmd, "", "", 0, False)
@@ -736,6 +751,7 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
         "popd": executeBuiltinPopd,
         "pushd": executeBuiltinPushd,
         "rm": executeBuiltinRm,
+        "umask": executeBuiltinUmask,
         ":": executeBuiltinColon,
     }
     # To avoid deadlock, we use a single stderr stream for piped
@@ -757,7 +773,7 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
                 #   env FOO=1 llc < %s | env BAR=2 llvm-mc | FileCheck %s
                 #   env FOO=1 %{another_env_plus_cmd} | FileCheck %s
                 if cmd_shenv is shenv:
-                    cmd_shenv = ShellEnvironment(shenv.cwd, shenv.env)
+                    cmd_shenv = ShellEnvironment(shenv.cwd, shenv.env, shenv.umask)
                 args = updateEnv(cmd_shenv, args)
                 if not args:
                     # Return the environment variables if no argument is provided.
@@ -902,6 +918,13 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
             args = quote_windows_command(args)
 
         try:
+            # TODO(boomanaiden154): We currently wrap the subprocess.Popen with
+            # os.umask as the umask argument in subprocess.Popen is not
+            # available before Python 3.9. Once LLVM requires at least Python
+            # 3.9, this code should be updated to use umask argument.
+            old_umask = -1
+            if cmd_shenv.umask != -1:
+                old_umask = os.umask(cmd_shenv.umask)
             procs.append(
                 subprocess.Popen(
                     args,
@@ -916,6 +939,8 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
                     errors="replace",
                 )
             )
+            if old_umask != -1:
+                os.umask(old_umask)
             proc_not_counts.append(not_count)
             # Let the helper know about this process
             timeoutHelper.addProcess(procs[-1])
diff --git a/llvm/utils/lit/tests/Inputs/shtest-umask/lit.cfg b/llvm/utils/lit/tests/Inputs/shtest-umask/lit.cfg
new file mode 100644
index 0000000000000..52e18b1d5c2b3
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-umask/lit.cfg
@@ -0,0 +1,7 @@
+import lit.formats
+
+config.name = "shtest-umask"
+config.suffixes = [".txt"]
+config.test_format = lit.formats.ShTest(execute_external=False)
+if sys.platform.startswith("win") or sys.platform.startswith("cygwin"):
+    config.available_features.add("system-windows")
diff --git a/llvm/utils/lit/tests/Inputs/shtest-umask/umask-bad-arg.txt b/llvm/utils/lit/tests/Inputs/shtest-umask/umask-bad-arg.txt
new file mode 100644
index 0000000000000..639bfd4b7b4f3
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-umask/umask-bad-arg.txt
@@ -0,0 +1 @@
+# RUN: umask bad
diff --git a/llvm/utils/lit/tests/Inputs/shtest-umask/umask-ok.txt b/llvm/utils/lit/tests/Inputs/shtest-umask/umask-ok.txt
new file mode 100644
index 0000000000000..9d43efbddf2cf
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-umask/umask-ok.txt
@@ -0,0 +1,11 @@
+## Windows has no umask so this test makes no sense.
+# UNSUPPORTED: system-windows
+
+# RUN: touch %t
+# RUN: chmod 644 %t && ls -l %t | cut -f 1 -d ' ' > %t.644
+# RUN: chmod 600 %t && ls -l %t | cut -f 1 -d ' ' > %t.600
+# RUN: chmod 666 %t && ls -l %t | cut -f 1 -d ' ' > %t.666
+
+# RUN: umask 022 && rm %t && touch %t && ls -l %t | cut -f 1 -d ' ' | cmp - %t.644
+# RUN: umask 177 && rm %t && touch %t && ls -l %t | cut -f 1 -d ' ' | cmp - %t.600
+# RUN: umask 000 && rm %t && touch %t && ls -l %t | cut -f 1 -d ' ' | cmp - %t.666
diff --git a/llvm/utils/lit/tests/Inputs/shtest-umask/umask-too-many-args.txt b/llvm/utils/lit/tests/Inputs/shtest-umask/umask-too-many-args.txt
new file mode 100644
index 0000000000000..0b7461b5bc3fe
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-umask/umask-too-many-args.txt
@@ -0,0 +1 @@
+# RUN: umask 0 0
diff --git a/llvm/utils/lit/tests/shtest-umask.py b/llvm/utils/lit/tests/shtest-umask.py
new file mode 100644
index 0000000000000..daec3cf479fc7
--- /dev/null
+++ b/llvm/utils/lit/tests/shtest-umask.py
@@ -0,0 +1,18 @@
+# Check the umask command
+
+# RUN: not %{lit} -a -v %{inputs}/shtest-umask | FileCheck -match-full-lines %s
+
+# CHECK: -- Testing: 3 tests{{.*}}
+
+# CHECK-LABEL: FAIL: shtest-umask :: umask-bad-arg.txt ({{[^)]*}})
+# CHECK: umask bad
+# CHECK: # | Error: 'umask': invalid literal {{.*}}
+
+# CHECK-LABEL: FAIL: shtest-umask :: umask-too-many-args.txt ({{[^)]*}})
+# CHECK: umask 0 0
+# CHECK: # | 'umask' supports only one argument
+
+# CHECK: Total Discovered Tests: 3
+# CHECK: {{Passed|Unsupported}}: 1 {{\([0-9]*\.[0-9]*%\)}}
+# CHECK: Failed{{ *}}: 2 {{\([0-9]*\.[0-9]*%\)}}
+# CHECK-NOT: {{.}}
    
    
More information about the llvm-commits
mailing list