68 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			68 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Python
		
	
	
	
| #
 | |
| #
 | |
| #
 | |
| 
 | |
| from __future__ import absolute_import, division, print_function, unicode_literals
 | |
| 
 | |
| #
 | |
| #
 | |
| #
 | |
| 
 | |
| import fcntl as _fcntl
 | |
| import os.path as _path
 | |
| import os as _os
 | |
| 
 | |
| from solaar import NAME
 | |
| _program = NAME.lower()
 | |
| del NAME
 | |
| 
 | |
| from logging import getLogger, DEBUG as _DEBUG
 | |
| _log = getLogger(__name__)
 | |
| del getLogger
 | |
| 
 | |
| 
 | |
| def check():
 | |
| 	"""Select a file lock location and try to acquire it.
 | |
| 	Suitable locations are $XDG_RUNTIME_DIR, /run/lock, /var/lock, and $TMPDIR.
 | |
| 	The first one found and writable is used.
 | |
| 	"""
 | |
| 	# ensure no more than a single instance runs at a time
 | |
| 	lock_fd = None
 | |
| 	for p in _os.environ.get('XDG_RUNTIME_DIR'), '/run/lock', '/var/lock', _os.environ.get('TMPDIR', '/tmp'):
 | |
| 		# pick the first temporary writable folder
 | |
| 		if p and _path.isdir(p) and _os.access(p, _os.W_OK):
 | |
| 			lock_path = _path.join(p, _program + '.single-instance.' + str(_os.getuid()))
 | |
| 			try:
 | |
| 				lock_fd = open(lock_path, 'wb')
 | |
| 				if _log.isEnabledFor(_DEBUG):
 | |
| 					_log.debug("single-instance lock file is %s", lock_path)
 | |
| 				break
 | |
| 			except:
 | |
| 				pass
 | |
| 
 | |
| 	if lock_fd:
 | |
| 		try:
 | |
| 			_fcntl.flock(lock_fd, _fcntl.LOCK_EX | _fcntl.LOCK_NB)
 | |
| 			if _log.isEnabledFor(_DEBUG):
 | |
| 				_log.debug("acquired single-instance lock %s", lock_fd)
 | |
| 			return lock_fd
 | |
| 		except IOError as e:
 | |
| 			if e.errno == 11:
 | |
| 				_log.warn("lock file is busy, %s already running: %s", _program, e)
 | |
| 				import sys
 | |
| 				sys.exit(_program + ": error: already running")
 | |
| 			else:
 | |
| 				raise
 | |
| 	else:
 | |
| 		import sys
 | |
| 		print (_program + ": warning: no suitable location for the lockfile found; ignoring", file=sys.stderr)
 | |
| 
 | |
| 
 | |
| def close(lock_fd):
 | |
| 	"""Release a file lock."""
 | |
| 	if lock_fd:
 | |
| 		_fcntl.flock(lock_fd, _fcntl.LOCK_UN)
 | |
| 		lock_fd.close()
 | |
| 		if _log.isEnabledFor(_DEBUG):
 | |
| 			_log.debug("released single-instance lock %s", lock_fd)
 |