Reading umask (thread-safe)
umask is inherited by child processes. You could create a pipe, fork a child process, get the umask there and write the result to the pipe so the parent can read it.
Quite expensive, but without any special requirements like /proc
virtual filesystem. An example with just low-level OS calls (all async-safe) and no error checking below:
import os
import struct
def get_umask():
pipe = os.pipe()
pid = os.fork()
if pid == 0:
os.close(pipe[0])
umask = os.umask(0)
os.write(pipe[1], struct.pack('H', umask))
os.close(pipe[1])
os._exit(0)
else:
os.close(pipe[1])
value = os.read(pipe[0], 2)
os.close(pipe[0])
os.waitpid(pid, 0)
return struct.unpack('H', value)[0]
print("umask {:03o}".format(get_umask()))
The only truly, unambiguously thread-safe way I know is to call a new process.
import subprocess
umask_cmd = ('python', '-c', 'import os; print(os.umask(0777))')
umask = int(subprocess.check_output(umask_cmd))
Note that if you have bash or another shell, you could also call that. Since it might be on a weird system, I've chosen to use a python subprocess in umask_cmd
, since you must have python. If you're on a non-weird *nix system, then you can use sh or bash instead.
if your system has Umask
field in /proc/[pid]/status
, you could read from on it:
import os
def getumask():
pid = os.getpid()
with open(f'/proc/{pid}/status') as f:
for l in f:
if l.startswith('Umask'):
return int(l.split()[1], base=8)
return None
tested under CentOS 7.5, Debian 9.6.
or, you could add a thread lock :)