Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading umask (thread-safe)

I know this pattern to read the umask in Python:

current_umask = os.umask(0)  # line1
os.umask(current_umask)      # line2
return current_umask         # line3

But this is not thread-safe.

A thread which executes between line1 and line2 will have a different umask.

Is there a thread-safe way to read the umask in Python?

Related: https://bugs.python.org/issue35275

like image 605
guettli Avatar asked Nov 09 '18 13:11

guettli


Video Answer


2 Answers

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 :)

like image 77
georgexsh Avatar answered Sep 18 '22 14:09

georgexsh


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()))
like image 20
VPfB Avatar answered Sep 18 '22 14:09

VPfB