Do not use a file for the single instance mutex on linux

This commit is contained in:
Kovid Goyal 2014-12-19 13:00:30 +05:30
parent d23edad6b9
commit e486e67d57
2 changed files with 38 additions and 23 deletions

View File

@ -391,10 +391,6 @@ def cant_start(msg=_('If you are sure it is not running')+', ',
where += _('lower right region of the screen.')
if iswindows or islinux:
what = _('try rebooting your computer.')
if islinux and not listener_failed:
from calibre.utils.lock import singleinstance_path
path = singleinstance_path(singleinstance_name)
what = _('try deleting the file: "%s"') % path
else:
if listener_failed:
path = gui_socket_address()
@ -464,7 +460,7 @@ def main(args=sys.argv):
except AbortInit:
return 1
from calibre.utils.lock import singleinstance
si = singleinstance('calibre GUI')
si = singleinstance(singleinstance_name)
if si and opts.shutdown_running_calibre:
return 0
if si:

View File

@ -6,8 +6,7 @@ __docformat__ = 'restructuredtext en'
Secure access to locked files from multiple processes.
'''
from calibre.constants import iswindows, __appname__, \
win32api, win32event, winerror, fcntl
from calibre.constants import iswindows, __appname__, islinux, win32api, win32event, winerror, fcntl
import time, atexit, os, stat, errno
class LockError(Exception):
@ -191,17 +190,8 @@ def _clean_lock_file(file):
except:
pass
def singleinstance_path(name):
return os.path.expanduser('~/.'+__appname__+'_'+name+'.lock')
def singleinstance(name):
'''
Return True if no other instance of the application identified by name is running,
False otherwise.
@param name: The name to lock.
@type name: string
'''
if iswindows:
if iswindows:
def singleinstance(name):
mutexname = 'mutexforsingleinstanceof'+__appname__+name
mutex = win32event.CreateMutex(None, False, mutexname)
err = win32api.GetLastError()
@ -212,14 +202,43 @@ def singleinstance(name):
elif mutex and err != winerror.ERROR_INVALID_HANDLE:
atexit.register(win32api.CloseHandle, mutex)
return not err == winerror.ERROR_ALREADY_EXISTS
else:
elif islinux:
def singleinstance(name):
import socket
from calibre.utils.ipc import eintr_retry_call
name = '%s-singleinstance-%s-%d' % (__appname__, name, os.geteuid())
if not isinstance(name, bytes):
name = name.encode('utf-8')
address = b'\0' + name.replace(b' ', b'_')
sock = socket.socket(family=socket.AF_UNIX)
try:
eintr_retry_call(sock.bind, address)
except socket.error as err:
if getattr(err, 'errno', None) == errno.EADDRINUSE:
return False
raise
fd = sock.fileno()
old_flags = fcntl.fcntl(fd, fcntl.F_GETFD)
fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC)
atexit.register(sock.close)
return True
else:
def singleinstance_path(name):
return os.path.expanduser('~/.'+__appname__+'_'+name+'.lock')
def singleinstance(name):
'''
Return True if no other instance of the application identified by name is running,
False otherwise.
@param name: The name to lock.
@type name: string
'''
path = singleinstance_path(name)
try:
f = open(path, 'w')
fcntl.lockf(f.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB)
atexit.register(_clean_lock_file, f)
return True
except IOError:
return False
return False
except EnvironmentError:
pass
return False