mercurial/lock.py
changeset 43077 687b865b95ad
parent 43076 2372284d9457
child 43089 c59eb1560c44
equal deleted inserted replaced
43076:2372284d9457 43077:687b865b95ad
    33     It's useful to detect "dead" processes and remove stale locks with
    33     It's useful to detect "dead" processes and remove stale locks with
    34     confidence. Typically it's just hostname. On modern linux, we include an
    34     confidence. Typically it's just hostname. On modern linux, we include an
    35     extra Linux-specific pid namespace identifier.
    35     extra Linux-specific pid namespace identifier.
    36     """
    36     """
    37     result = encoding.strtolocal(socket.gethostname())
    37     result = encoding.strtolocal(socket.gethostname())
    38     if pycompat.sysplatform.startswith('linux'):
    38     if pycompat.sysplatform.startswith(b'linux'):
    39         try:
    39         try:
    40             result += '/%x' % os.stat('/proc/self/ns/pid').st_ino
    40             result += b'/%x' % os.stat(b'/proc/self/ns/pid').st_ino
    41         except OSError as ex:
    41         except OSError as ex:
    42             if ex.errno not in (errno.ENOENT, errno.EACCES, errno.ENOTDIR):
    42             if ex.errno not in (errno.ENOENT, errno.EACCES, errno.ENOTDIR):
    43                 raise
    43                 raise
    44     return result
    44     return result
    45 
    45 
    74             raiseinterrupt(num)
    74             raiseinterrupt(num)
    75 
    75 
    76     try:
    76     try:
    77         # save handlers first so they can be restored even if a setup is
    77         # save handlers first so they can be restored even if a setup is
    78         # interrupted between signal.signal() and orighandlers[] =.
    78         # interrupted between signal.signal() and orighandlers[] =.
    79         for name in ['CTRL_C_EVENT', 'SIGINT', 'SIGBREAK', 'SIGHUP', 'SIGTERM']:
    79         for name in [
       
    80             b'CTRL_C_EVENT',
       
    81             b'SIGINT',
       
    82             b'SIGBREAK',
       
    83             b'SIGHUP',
       
    84             b'SIGTERM',
       
    85         ]:
    80             num = getattr(signal, name, None)
    86             num = getattr(signal, name, None)
    81             if num and num not in orighandlers:
    87             if num and num not in orighandlers:
    82                 orighandlers[num] = signal.getsignal(num)
    88                 orighandlers[num] = signal.getsignal(num)
    83         try:
    89         try:
    84             for num in orighandlers:
    90             for num in orighandlers:
   112     the held lock while trying to acquires it."""
   118     the held lock while trying to acquires it."""
   113 
   119 
   114     def printwarning(printer, locker):
   120     def printwarning(printer, locker):
   115         """issue the usual "waiting on lock" message through any channel"""
   121         """issue the usual "waiting on lock" message through any channel"""
   116         # show more details for new-style locks
   122         # show more details for new-style locks
   117         if ':' in locker:
   123         if b':' in locker:
   118             host, pid = locker.split(":", 1)
   124             host, pid = locker.split(b":", 1)
   119             msg = _(
   125             msg = _(
   120                 "waiting for lock on %s held by process %r on host %r\n"
   126                 b"waiting for lock on %s held by process %r on host %r\n"
   121             ) % (
   127             ) % (
   122                 pycompat.bytestr(l.desc),
   128                 pycompat.bytestr(l.desc),
   123                 pycompat.bytestr(pid),
   129                 pycompat.bytestr(pid),
   124                 pycompat.bytestr(host),
   130                 pycompat.bytestr(host),
   125             )
   131             )
   126         else:
   132         else:
   127             msg = _("waiting for lock on %s held by %r\n") % (
   133             msg = _(b"waiting for lock on %s held by %r\n") % (
   128                 l.desc,
   134                 l.desc,
   129                 pycompat.bytestr(locker),
   135                 pycompat.bytestr(locker),
   130             )
   136             )
   131         printer(msg)
   137         printer(msg)
   132 
   138 
   157             delay += 1
   163             delay += 1
   158 
   164 
   159     l.delay = delay
   165     l.delay = delay
   160     if l.delay:
   166     if l.delay:
   161         if 0 <= warningidx <= l.delay:
   167         if 0 <= warningidx <= l.delay:
   162             ui.warn(_("got lock after %d seconds\n") % l.delay)
   168             ui.warn(_(b"got lock after %d seconds\n") % l.delay)
   163         else:
   169         else:
   164             ui.debug("got lock after %d seconds\n" % l.delay)
   170             ui.debug(b"got lock after %d seconds\n" % l.delay)
   165     if l.acquirefn:
   171     if l.acquirefn:
   166         l.acquirefn()
   172         l.acquirefn()
   167     return l
   173     return l
   168 
   174 
   169 
   175 
   266         if self.held:
   272         if self.held:
   267             self.held += 1
   273             self.held += 1
   268             return
   274             return
   269         if lock._host is None:
   275         if lock._host is None:
   270             lock._host = _getlockprefix()
   276             lock._host = _getlockprefix()
   271         lockname = '%s:%d' % (lock._host, self.pid)
   277         lockname = b'%s:%d' % (lock._host, self.pid)
   272         retry = 5
   278         retry = 5
   273         while not self.held and retry:
   279         while not self.held and retry:
   274             retry -= 1
   280             retry -= 1
   275             try:
   281             try:
   276                 with self._maybedelayedinterrupt():
   282                 with self._maybedelayedinterrupt():
   305 
   311 
   306         if not self.held:
   312         if not self.held:
   307             # use empty locker to mean "busy for frequent lock/unlock
   313             # use empty locker to mean "busy for frequent lock/unlock
   308             # by many processes"
   314             # by many processes"
   309             raise error.LockHeld(
   315             raise error.LockHeld(
   310                 errno.EAGAIN, self.vfs.join(self.f), self.desc, ""
   316                 errno.EAGAIN, self.vfs.join(self.f), self.desc, b""
   311             )
   317             )
   312 
   318 
   313     def _readlock(self):
   319     def _readlock(self):
   314         """read lock and return its value
   320         """read lock and return its value
   315 
   321 
   325 
   331 
   326     def _testlock(self, locker):
   332     def _testlock(self, locker):
   327         if locker is None:
   333         if locker is None:
   328             return None
   334             return None
   329         try:
   335         try:
   330             host, pid = locker.split(":", 1)
   336             host, pid = locker.split(b":", 1)
   331         except ValueError:
   337         except ValueError:
   332             return locker
   338             return locker
   333         if host != lock._host:
   339         if host != lock._host:
   334             return locker
   340             return locker
   335         try:
   341         try:
   339         if procutil.testpid(pid):
   345         if procutil.testpid(pid):
   340             return locker
   346             return locker
   341         # if locker dead, break lock.  must do this with another lock
   347         # if locker dead, break lock.  must do this with another lock
   342         # held, or can race and break valid lock.
   348         # held, or can race and break valid lock.
   343         try:
   349         try:
   344             l = lock(self.vfs, self.f + '.break', timeout=0)
   350             l = lock(self.vfs, self.f + b'.break', timeout=0)
   345             self.vfs.unlink(self.f)
   351             self.vfs.unlink(self.f)
   346             l.release()
   352             l.release()
   347         except error.LockError:
   353         except error.LockError:
   348             return locker
   354             return locker
   349 
   355 
   369         Communicating this string to the subprocess needs to be done separately
   375         Communicating this string to the subprocess needs to be done separately
   370         -- typically by an environment variable.
   376         -- typically by an environment variable.
   371         """
   377         """
   372         if not self.held:
   378         if not self.held:
   373             raise error.LockInheritanceContractViolation(
   379             raise error.LockInheritanceContractViolation(
   374                 'inherit can only be called while lock is held'
   380                 b'inherit can only be called while lock is held'
   375             )
   381             )
   376         if self._inherited:
   382         if self._inherited:
   377             raise error.LockInheritanceContractViolation(
   383             raise error.LockInheritanceContractViolation(
   378                 'inherit cannot be called while lock is already inherited'
   384                 b'inherit cannot be called while lock is already inherited'
   379             )
   385             )
   380         if self._inheritchecker is not None:
   386         if self._inheritchecker is not None:
   381             self._inheritchecker()
   387             self._inheritchecker()
   382         if self.releasefn:
   388         if self.releasefn:
   383             self.releasefn()
   389             self.releasefn()