This file is indexed.

/usr/lib/python3/dist-packages/instant/locking.py is in python3-instant 2016.2.0-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
"""File locking for the cache system, to avoid problems
when multiple processes work with the same module.
Only works on UNIX systems.

Two Python libraries can be used:

  flufl.lock : A nfs safe which can be downloaded from:

                 https://launchpad.net/flufl.lock

  fcntl      : A builtin Python module which only works on posix machines
               and it is does unfortunately not work on nfs

"""

# Copyright (C) 2009 Martin Sandve Alnes
# Copyright (C) 2011-2013 Johan Hake
#
# This file is part of Instant.
#
# Instant is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Instant is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Instant. If not, see <http://www.gnu.org/licenses/>.
#
# Alternatively, Instant may be distributed under the terms of the BSD license.

__all__ = ["get_lock", "release_lock", "release_all_lock", "file_lock"]

import os.path
from .output import instant_error, instant_assert, instant_debug
from .paths import validate_cache_dir

try:
    import flufl.lock
    fcntl = None
except:
    flufl = None
    try:
        import fcntl
    except:
        fcntl = None

# Keeping an overview of locks currently held, to avoid deadlocks
# within a single process
_lock_names = {} # lock.fileno() -> lockname
_lock_files = {} # lockname -> lock
_lock_count = {} # lockname -> number of times this lock has been aquired and not yet released

if flufl:
    def get_lock(cache_dir, module_name):
        "Get a new file lock."

        from flufl.lock import Lock
        from datetime import timedelta

        lockname = module_name + ".lock"
        count = _lock_count.get(lockname, 0)

        instant_debug("Acquiring lock %s, count is %d." % (lockname, count))

        cache_dir = validate_cache_dir(cache_dir)
        lockname = os.path.join(cache_dir, lockname)
        lock = Lock(lockname)
        lock.lock()

        return lock

    def release_lock(lock):
        "Release a lock currently held by Instant."
        if lock.is_locked:
            hostname, pid, lockname = lock.details
            instant_debug("Releasing lock %s." % (lockname))
            lock.unlock()

    def release_all_locks():
        pass

elif fcntl:
    def get_lock(cache_dir, module_name):
        "Get a new file lock."
        global _lock_names, _lock_files, _lock_count

        lockname = module_name + ".lock"
        count = _lock_count.get(lockname, 0)
        import inspect
        frame = inspect.currentframe().f_back
        instant_debug("Acquiring lock %s, count is %d. Called from: %s line: %d" % \
                      (lockname, count, inspect.getfile(frame), frame.f_lineno))

        if count == 0:
            cache_dir = validate_cache_dir(cache_dir)
            lock = open(os.path.join(cache_dir, lockname), "w")
            fcntl.flock(lock.fileno(), fcntl.LOCK_EX)
            _lock_names[lock.fileno()] = lockname
            _lock_files[lockname] = lock
        else:
            lock = _lock_files[lockname]

        _lock_count[lockname] = count + 1
        return lock

    def release_lock(lock):
        "Release a lock currently held by Instant."
        global _lock_names, _lock_files, _lock_count

        lockname = _lock_names[lock.fileno()]
        count = _lock_count[lockname]

        import inspect
        frame = inspect.currentframe().f_back

        instant_debug("Releasing lock %s, count is %d. Called from: %s line: %d" % \
                      (lockname, count, inspect.getfile(frame), frame.f_lineno))

        instant_assert(count > 0, "Releasing lock that Instant is supposedly not holding.")
        instant_assert(lock is _lock_files[lockname], "Lock mismatch, might be something wrong in locking logic.")

        del _lock_files[lockname]
        del _lock_names[lock.fileno()]
        _lock_count[lockname] = count - 1

        fcntl.flock(lock.fileno(), fcntl.LOCK_UN)
        lock.close()

    def release_all_locks():
        "Release all locks currently held by Instant."
        locks = list(_lock_files.values())
        for lock in locks:
            release_lock(lock)
        instant_assert(all(_lock_count[lockname] == 0 for lockname in _lock_count), "Lock counts not zero after releasing all locks.")

else:
    # Windows systems have no fcntl, implement these otherwise if
    # locking is needed on windows
    def get_lock(cache_dir, module_name):
        return None

    def release_lock(lock):
        pass

    def release_all_locks():
        pass


class file_lock(object):
    """
    File lock using with statement
    """
    def __init__(self, cache_dir, module_name):
        self.cache_dir = cache_dir
        self.module_name = module_name

    def __enter__(self):
        self.lock = get_lock(self.cache_dir, self.module_name)
        return self.lock

    def __exit__(self, type, value, tb):
        release_lock(self.lock)