mirror of
https://github.com/borgbackup/borg.git
synced 2025-02-23 14:41:43 +00:00
Move platform-dependent code to platform package
This commit is contained in:
parent
d490292be3
commit
c562f7750c
3 changed files with 62 additions and 43 deletions
|
@ -6,47 +6,11 @@
|
|||
import time
|
||||
|
||||
from .helpers import Error, ErrorWithTraceback
|
||||
from .platform import process_alive, get_process_id
|
||||
|
||||
ADD, REMOVE = 'add', 'remove'
|
||||
SHARED, EXCLUSIVE = 'shared', 'exclusive'
|
||||
|
||||
# only determine the PID and hostname once.
|
||||
# for FUSE mounts, we fork a child process that needs to release
|
||||
# the lock made by the parent, so it needs to use the same PID for that.
|
||||
_pid = os.getpid()
|
||||
_hostname = socket.gethostname()
|
||||
|
||||
|
||||
def get_id():
|
||||
"""Get identification tuple for 'us'"""
|
||||
|
||||
# If changing the thread_id to ever be non-zero, also revisit the check_lock_stale() below.
|
||||
thread_id = 0
|
||||
return _hostname, _pid, thread_id
|
||||
|
||||
|
||||
def check_lock_stale(host, pid, thread):
|
||||
"""Check if the host, pid, thread combination corresponds to a dead process on our local node or not."""
|
||||
if host != _hostname:
|
||||
return False
|
||||
|
||||
if thread != 0:
|
||||
# Currently thread is always 0, if we ever decide to set this to a non-zero value, this code needs to be revisited too to do a sensible thing
|
||||
return False
|
||||
|
||||
try:
|
||||
# This may not work in Windows.
|
||||
# This does not kill anything, 0 means "see if we can send a signal to this process or not".
|
||||
# Possible errors: No such process (== stale lock) or permission denied (not a stale lock)
|
||||
# If the exception is not raised that means such a pid is valid and we can send a signal to it (== not a stale lock too).
|
||||
os.kill(pid, 0)
|
||||
return False
|
||||
except OSError as err:
|
||||
if err.errno != errno.ESRCH:
|
||||
return False
|
||||
pass
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class TimeoutTimer:
|
||||
|
@ -141,7 +105,7 @@ def __init__(self, path, timeout=None, sleep=None, id=None, kill_stale_locks=Fal
|
|||
self.timeout = timeout
|
||||
self.sleep = sleep
|
||||
self.path = os.path.abspath(path)
|
||||
self.id = id or get_id()
|
||||
self.id = id or get_process_id()
|
||||
self.unique_name = os.path.join(self.path, "%s.%d-%x" % self.id)
|
||||
self.ok_to_kill_stale_locks = kill_stale_locks
|
||||
self.stale_warning_printed = False
|
||||
|
@ -194,7 +158,6 @@ def by_me(self):
|
|||
|
||||
def kill_stale_lock(self):
|
||||
for name in os.listdir(self.path):
|
||||
|
||||
try:
|
||||
host_pid, thread_str = name.rsplit('-', 1)
|
||||
host, pid_str = host_pid.rsplit('.', 1)
|
||||
|
@ -205,7 +168,7 @@ def kill_stale_lock(self):
|
|||
# It's safer to just exit
|
||||
return False
|
||||
|
||||
if not check_lock_stale(host, pid, thread):
|
||||
if not process_alive(host, pid, thread):
|
||||
return False
|
||||
|
||||
if not self.ok_to_kill_stale_locks:
|
||||
|
@ -249,7 +212,7 @@ class LockRoster:
|
|||
"""
|
||||
def __init__(self, path, id=None, kill_stale_locks=False):
|
||||
self.path = path
|
||||
self.id = id or get_id()
|
||||
self.id = id or get_process_id()
|
||||
self.ok_to_kill_zombie_locks = kill_stale_locks
|
||||
|
||||
def load(self):
|
||||
|
@ -264,7 +227,7 @@ def load(self):
|
|||
try:
|
||||
for e in data[key]:
|
||||
(host, pid, thread) = e
|
||||
if not check_lock_stale(host, pid, thread):
|
||||
if not process_alive(host, pid, thread):
|
||||
elements.add(tuple(e))
|
||||
else:
|
||||
print(("Removed stale %s roster lock for pid %d." % (key, pid)), file=sys.stderr)
|
||||
|
@ -330,7 +293,7 @@ def __init__(self, path, exclusive=False, sleep=None, timeout=None, id=None, kil
|
|||
self.is_exclusive = exclusive
|
||||
self.sleep = sleep
|
||||
self.timeout = timeout
|
||||
self.id = id or get_id()
|
||||
self.id = id or get_process_id()
|
||||
# globally keeping track of shared and exclusive lockers:
|
||||
self._roster = LockRoster(path + '.roster', id=id, kill_stale_locks=kill_stale_locks)
|
||||
# an exclusive lock, used for:
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
from .base import set_flags, get_flags
|
||||
from .base import SaveFile, SyncFile, sync_dir, fdatasync
|
||||
from .base import swidth, API_VERSION
|
||||
from .posix import process_alive, get_process_id, local_pid_alive
|
||||
|
||||
if sys.platform.startswith('linux'): # pragma: linux only
|
||||
from .linux import acl_get, acl_set
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
|
||||
import errno
|
||||
import os
|
||||
import socket
|
||||
|
||||
cdef extern from "wchar.h":
|
||||
cdef int wcswidth(const Py_UNICODE *str, size_t n)
|
||||
|
||||
|
@ -8,3 +13,53 @@ def swidth(s):
|
|||
return terminal_width
|
||||
else:
|
||||
return str_len
|
||||
|
||||
|
||||
# only determine the PID and hostname once.
|
||||
# for FUSE mounts, we fork a child process that needs to release
|
||||
# the lock made by the parent, so it needs to use the same PID for that.
|
||||
_pid = os.getpid()
|
||||
# XXX this sometimes requires live internet access for issuing a DNS query in the background.
|
||||
_hostname = socket.gethostname()
|
||||
|
||||
|
||||
def get_process_id():
|
||||
"""
|
||||
Return identification tuple (hostname, pid, thread_id) for 'us'. If this is a FUSE process, then the PID will be
|
||||
that of the parent, not the forked FUSE child.
|
||||
|
||||
Note: Currently thread_id is *always* zero.
|
||||
"""
|
||||
thread_id = 0
|
||||
return _hostname, _pid, thread_id
|
||||
|
||||
|
||||
def process_alive(host, pid, thread):
|
||||
"""Check if the (host, pid, thread_id) combination corresponds to a dead process on our local node or not."""
|
||||
from . import local_pid_alive
|
||||
|
||||
if host != _hostname:
|
||||
return False
|
||||
|
||||
if thread != 0:
|
||||
# Currently thread is always 0, if we ever decide to set this to a non-zero value,
|
||||
# this code needs to be revisited, too, to do a sensible thing
|
||||
return False
|
||||
|
||||
return local_pid_alive
|
||||
|
||||
def local_pid_alive(pid):
|
||||
"""Return whether *pid* is alive."""
|
||||
try:
|
||||
# This doesn't work on Windows.
|
||||
# This does not kill anything, 0 means "see if we can send a signal to this process or not".
|
||||
# Possible errors: No such process (== stale lock) or permission denied (not a stale lock)
|
||||
# If the exception is not raised that means such a pid is valid and we can send a signal to it.
|
||||
os.kill(pid, 0)
|
||||
return True
|
||||
except OSError as err:
|
||||
if err.errno == errno.ESRCH:
|
||||
# ESRCH = no such process
|
||||
return False
|
||||
# Any other error (eg. permissions) mean that the process ID refers to a live process
|
||||
return True
|
Loading…
Reference in a new issue