mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-05-27 10:44:33 +00:00
email: mutex: create lock file as plinth user
This commit is contained in:
parent
df14e74972
commit
7397326d57
@ -5,8 +5,8 @@ import fcntl
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import pwd
|
import pwd
|
||||||
|
import subprocess
|
||||||
import threading
|
import threading
|
||||||
import time
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -35,7 +35,6 @@ class Mutex:
|
|||||||
# Set up
|
# Set up
|
||||||
fd = self._open_lock_file()
|
fd = self._open_lock_file()
|
||||||
fcntl.lockf(fd, fcntl.LOCK_EX)
|
fcntl.lockf(fd, fcntl.LOCK_EX)
|
||||||
self._chmod_and_chown(fd)
|
|
||||||
# Enter context
|
# Enter context
|
||||||
try:
|
try:
|
||||||
yield
|
yield
|
||||||
@ -46,33 +45,30 @@ class Mutex:
|
|||||||
|
|
||||||
def _open_lock_file(self):
|
def _open_lock_file(self):
|
||||||
"""Attempt to open lock file for R&W. Raises OSError on failure"""
|
"""Attempt to open lock file for R&W. Raises OSError on failure"""
|
||||||
attempts = 10
|
|
||||||
errno = -1
|
|
||||||
fd = None
|
|
||||||
# Simulate a spin lock
|
|
||||||
while attempts > 0:
|
|
||||||
errno, fd = self._try(lambda: open(self.lock_path, 'wb'))
|
|
||||||
if errno == 0:
|
|
||||||
return fd
|
|
||||||
else:
|
|
||||||
attempts -= 1
|
|
||||||
time.sleep(0.25)
|
|
||||||
raise OSError(errno, os.strerror(errno))
|
|
||||||
|
|
||||||
def _chmod_and_chown(self, fd):
|
|
||||||
"""If the process UID is root, set fd's mode and ownership to
|
|
||||||
appropriate values. If we are not root, only set the mode"""
|
|
||||||
if os.getuid() == 0:
|
if os.getuid() == 0:
|
||||||
user_info = pwd.getpwnam('plinth')
|
if os.path.exists(self.lock_path):
|
||||||
os.fchown(fd.fileno(), 0, 0)
|
# Check its owner and mode
|
||||||
os.fchmod(fd.fileno(), 0o660) # rw-rw----
|
stat = os.stat(self.lock_path)
|
||||||
fd.truncate(0)
|
owner = pwd.getpwuid(stat.st_uid).pw_name
|
||||||
os.fchown(fd.fileno(), user_info.pw_uid, user_info.pw_gid)
|
mode = stat.st_mode & 0o777
|
||||||
else:
|
if owner != 'plinth' or mode != 0o600:
|
||||||
errno, _ = self._try(lambda: os.fchmod(fd.fileno(), 0o660))
|
logger.warning('Clean up bad file %s', self.lock_path)
|
||||||
if errno != 0:
|
os.unlink(self.lock_path)
|
||||||
logger.warning('chmod failed, lock path %s, errno %d',
|
self._create_lock_file_as_plinth()
|
||||||
self.lock_path, errno)
|
else:
|
||||||
|
self._create_lock_file_as_plinth()
|
||||||
|
|
||||||
|
return open(self.lock_path, 'wb+')
|
||||||
|
|
||||||
|
def _create_lock_file_as_plinth(self):
|
||||||
|
args = ['sudo', '-n', '-u', 'plinth', 'touch', self.lock_path]
|
||||||
|
completed = subprocess.run(args, capture_output=True)
|
||||||
|
if completed.returncode != 0:
|
||||||
|
logger.critical('Process returned %d', completed.returncode)
|
||||||
|
logger.critical('Stdout: %r', completed.stdout)
|
||||||
|
logger.critical('Stderr: %r', completed.stderr)
|
||||||
|
raise OSError('Could not create ' + self.lock_path)
|
||||||
|
os.chmod(self.lock_path, 0o600)
|
||||||
|
|
||||||
def _try(self, function):
|
def _try(self, function):
|
||||||
try:
|
try:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user