|  | @@ -1,3 +1,4 @@
 | 
	
		
			
				|  |  | +import errno
 | 
	
		
			
				|  |  |  import json
 | 
	
		
			
				|  |  |  import os
 | 
	
		
			
				|  |  |  import time
 | 
	
	
		
			
				|  | @@ -163,7 +164,7 @@ class ExclusiveLock:
 | 
	
		
			
				|  |  |                  thread = int(thread_str)
 | 
	
		
			
				|  |  |              except ValueError:
 | 
	
		
			
				|  |  |                  # Malformed lock name? Or just some new format we don't understand?
 | 
	
		
			
				|  |  | -                # It's safer to just exit.
 | 
	
		
			
				|  |  | +                logger.error("Found malformed lock %s in %s. Please check/fix manually.", name, self.path)
 | 
	
		
			
				|  |  |                  return False
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              if platform.process_alive(host, pid, thread):
 | 
	
	
		
			
				|  | @@ -172,7 +173,7 @@ class ExclusiveLock:
 | 
	
		
			
				|  |  |              if not self.kill_stale_locks:
 | 
	
		
			
				|  |  |                  if not self.stale_warning_printed:
 | 
	
		
			
				|  |  |                      # Log this at warning level to hint the user at the ability
 | 
	
		
			
				|  |  | -                    logger.warning("Found stale lock %s, but not deleting because BORG_HOSTNAME_IS_UNIQUE is not set.", name)
 | 
	
		
			
				|  |  | +                    logger.warning("Found stale lock %s, but not deleting because BORG_HOSTNAME_IS_UNIQUE is False.", name)
 | 
	
		
			
				|  |  |                      self.stale_warning_printed = True
 | 
	
		
			
				|  |  |                  return False
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -188,10 +189,12 @@ class ExclusiveLock:
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          try:
 | 
	
		
			
				|  |  |              os.rmdir(self.path)
 | 
	
		
			
				|  |  | -        except OSError:
 | 
	
		
			
				|  |  | -            # Directory is not empty = we lost the race to somebody else
 | 
	
		
			
				|  |  | -            # Permission denied = we cannot operate anyway
 | 
	
		
			
				|  |  | -            # other error like EIO = we cannot operate and it's unsafe too.
 | 
	
		
			
				|  |  | +        except OSError as err:
 | 
	
		
			
				|  |  | +            if err.errno == errno.ENOTEMPTY:
 | 
	
		
			
				|  |  | +                # Directory is not empty = we lost the race to somebody else
 | 
	
		
			
				|  |  | +                return False
 | 
	
		
			
				|  |  | +            # EACCES or EIO or ... = we cannot operate anyway
 | 
	
		
			
				|  |  | +            logger.error('Failed to remove lock dir: %s', str(err))
 | 
	
		
			
				|  |  |              return False
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          return True
 | 
	
	
		
			
				|  | @@ -242,7 +245,8 @@ class LockRoster:
 | 
	
		
			
				|  |  |                          if platform.process_alive(host, pid, thread):
 | 
	
		
			
				|  |  |                              elements.add((host, pid, thread))
 | 
	
		
			
				|  |  |                          else:
 | 
	
		
			
				|  |  | -                            logger.warning('Removed stale %s roster lock for pid %d.', key, pid)
 | 
	
		
			
				|  |  | +                            logger.warning('Removed stale %s roster lock for host %s pid %d thread %d.',
 | 
	
		
			
				|  |  | +                                           key, host, pid, thread)
 | 
	
		
			
				|  |  |                      data[key] = list(elements)
 | 
	
		
			
				|  |  |          except (FileNotFoundError, ValueError):
 | 
	
		
			
				|  |  |              # no or corrupt/empty roster file?
 |