Gentoo Archives: gentoo-commits

From: Zac Medico <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: pym/portage/
Date: Sun, 02 Oct 2016 04:46:37
Message-Id: 1475382815.5ef5fbaab88de47d4dbab333661d3525261d7633.zmedico@gentoo
1 commit: 5ef5fbaab88de47d4dbab333661d3525261d7633
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Mon Sep 26 06:26:35 2016 +0000
4 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
5 CommitDate: Sun Oct 2 04:33:35 2016 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=5ef5fbaa
7
8 locks: use fcntl.flock if fcntl.lockf is broken (bug 595146)
9
10 This is needed for Windows Subsystem for Linux (WSL), as well as
11 older versions of PyPy.
12
13 X-Gentoo-bug: 595146
14 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=595146
15 Acked-by: Brian Dolbec <dolsen <AT> gentoo.org>
16
17 pym/portage/locks.py | 59 +++++++++++++++++++++++++++++++++++++++++++++-------
18 1 file changed, 52 insertions(+), 7 deletions(-)
19
20 diff --git a/pym/portage/locks.py b/pym/portage/locks.py
21 index 42ff1e3..f61e181 100644
22 --- a/pym/portage/locks.py
23 +++ b/pym/portage/locks.py
24 @@ -8,8 +8,9 @@ __all__ = ["lockdir", "unlockdir", "lockfile", "unlockfile", \
25
26 import errno
27 import fcntl
28 -import platform
29 +import multiprocessing
30 import sys
31 +import tempfile
32 import time
33 import warnings
34
35 @@ -27,17 +28,61 @@ if sys.hexversion >= 0x3000000:
36
37 HARDLINK_FD = -2
38 _HARDLINK_POLL_LATENCY = 3 # seconds
39 -_default_lock_fn = fcntl.lockf
40 -
41 -if platform.python_implementation() == 'PyPy':
42 - # workaround for https://bugs.pypy.org/issue747
43 - _default_lock_fn = fcntl.flock
44
45 # Used by emerge in order to disable the "waiting for lock" message
46 # so that it doesn't interfere with the status display.
47 _quiet = False
48
49
50 +_lock_fn = None
51 +
52 +
53 +def _get_lock_fn():
54 + """
55 + Returns fcntl.lockf if proven to work, and otherwise returns fcntl.flock.
56 + On some platforms fcntl.lockf is known to be broken.
57 + """
58 + global _lock_fn
59 + if _lock_fn is not None:
60 + return _lock_fn
61 +
62 + def _test_lock(fd, lock_path):
63 + os.close(fd)
64 + try:
65 + with open(lock_path, 'a') as f:
66 + fcntl.lockf(f.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB)
67 + except EnvironmentError as e:
68 + if e.errno == errno.EAGAIN:
69 + # Parent process holds lock, as expected.
70 + sys.exit(0)
71 +
72 + # Something went wrong.
73 + sys.exit(1)
74 +
75 + fd, lock_path = tempfile.mkstemp()
76 + try:
77 + try:
78 + fcntl.lockf(fd, fcntl.LOCK_EX)
79 + except EnvironmentError:
80 + pass
81 + else:
82 + proc = multiprocessing.Process(target=_test_lock,
83 + args=(fd, lock_path))
84 + proc.start()
85 + proc.join()
86 + if proc.exitcode == os.EX_OK:
87 + # Use fcntl.lockf because the test passed.
88 + _lock_fn = fcntl.lockf
89 + return _lock_fn
90 + finally:
91 + os.close(fd)
92 + os.unlink(lock_path)
93 +
94 + # Fall back to fcntl.flock.
95 + _lock_fn = fcntl.flock
96 + return _lock_fn
97 +
98 +
99 _open_fds = set()
100
101 def _close_fds():
102 @@ -146,7 +191,7 @@ def lockfile(mypath, wantnewlockfile=0, unlinkfile=0,
103
104 # try for a non-blocking lock, if it's held, throw a message
105 # we're waiting on lockfile and use a blocking attempt.
106 - locking_method = portage._eintr_func_wrapper(_default_lock_fn)
107 + locking_method = portage._eintr_func_wrapper(_get_lock_fn())
108 try:
109 if "__PORTAGE_TEST_HARDLINK_LOCKS" in os.environ:
110 raise IOError(errno.ENOSYS, "Function not implemented")