2015-08-30 15:27:35 +08:00
|
|
|
import ctypes
|
|
|
|
import logging
|
2017-10-01 22:59:17 +08:00
|
|
|
import sys
|
2015-08-30 15:27:35 +08:00
|
|
|
from abc import ABCMeta, abstractmethod
|
2017-10-01 22:59:17 +08:00
|
|
|
|
2015-08-30 15:27:35 +08:00
|
|
|
from config import WormConfiguration
|
|
|
|
|
|
|
|
__author__ = 'itamar'
|
|
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
2015-11-30 16:56:20 +08:00
|
|
|
|
2015-08-30 15:27:35 +08:00
|
|
|
class _SystemSingleton(object):
|
|
|
|
__metaclass__ = ABCMeta
|
|
|
|
|
|
|
|
@property
|
|
|
|
@abstractmethod
|
|
|
|
def locked(self):
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def try_lock(self):
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def unlock(self):
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
|
|
|
|
class WindowsSystemSingleton(_SystemSingleton):
|
|
|
|
def __init__(self):
|
2017-10-01 22:59:17 +08:00
|
|
|
self._mutex_name = r"Global\%s" % (WormConfiguration.singleton_mutex_name,)
|
2015-08-30 15:27:35 +08:00
|
|
|
self._mutex_handle = None
|
|
|
|
|
|
|
|
@property
|
|
|
|
def locked(self):
|
|
|
|
return self._mutex_handle is not None
|
|
|
|
|
|
|
|
def try_lock(self):
|
|
|
|
assert self._mutex_handle is None, "Singleton already locked"
|
|
|
|
|
|
|
|
handle = ctypes.windll.kernel32.CreateMutexA(None,
|
|
|
|
ctypes.c_bool(True),
|
|
|
|
ctypes.c_char_p(self._mutex_name))
|
|
|
|
last_error = ctypes.windll.kernel32.GetLastError()
|
|
|
|
if not handle:
|
|
|
|
LOG.error("Cannot acquire system singleton %r, unknown error %d",
|
2015-11-30 16:56:20 +08:00
|
|
|
self._mutex_name, last_error)
|
2015-08-30 15:27:35 +08:00
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
if winerror.ERROR_ALREADY_EXISTS == last_error:
|
|
|
|
LOG.debug("Cannot acquire system singleton %r, mutex already exist",
|
|
|
|
self._mutex_name)
|
|
|
|
|
|
|
|
return False
|
2017-10-01 22:59:17 +08:00
|
|
|
|
2015-08-30 15:27:35 +08:00
|
|
|
self._mutex_handle = handle
|
|
|
|
|
|
|
|
LOG.debug("Global singleton mutex %r acquired",
|
|
|
|
self._mutex_name)
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
def unlock(self):
|
|
|
|
assert self._mutex_handle is not None, "Singleton not locked"
|
|
|
|
|
|
|
|
ctypes.windll.kernel32.CloseHandle(self._mutex_handle)
|
|
|
|
self._mutex_handle = None
|
|
|
|
|
|
|
|
|
|
|
|
class LinuxSystemSingleton(_SystemSingleton):
|
2015-09-29 22:51:44 +08:00
|
|
|
def __init__(self):
|
|
|
|
self._unix_sock_name = str(WormConfiguration.singleton_mutex_name)
|
|
|
|
self._sock_handle = None
|
|
|
|
|
2015-08-30 15:27:35 +08:00
|
|
|
@property
|
|
|
|
def locked(self):
|
2015-09-29 22:51:44 +08:00
|
|
|
return self._sock_handle is not None
|
2015-08-30 15:27:35 +08:00
|
|
|
|
|
|
|
def try_lock(self):
|
2015-09-29 22:51:44 +08:00
|
|
|
assert self._sock_handle is None, "Singleton already locked"
|
2017-10-01 22:59:17 +08:00
|
|
|
|
2015-09-29 22:51:44 +08:00
|
|
|
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
2017-10-01 22:59:17 +08:00
|
|
|
|
2015-09-29 22:51:44 +08:00
|
|
|
try:
|
|
|
|
sock.bind('\0' + self._unix_sock_name)
|
2017-10-01 22:59:17 +08:00
|
|
|
except socket.error as e:
|
2015-09-29 22:51:44 +08:00
|
|
|
LOG.error("Cannot acquire system singleton %r, error code %d, error: %s",
|
2015-11-30 16:56:20 +08:00
|
|
|
self._unix_sock_name, e.args[0], e.args[1])
|
2015-09-29 22:51:44 +08:00
|
|
|
return False
|
2017-10-01 22:59:17 +08:00
|
|
|
|
2015-09-29 22:51:44 +08:00
|
|
|
self._sock_handle = sock
|
|
|
|
|
2015-11-30 16:56:20 +08:00
|
|
|
LOG.debug("Global singleton mutex %r acquired", self._unix_sock_name)
|
2015-09-29 22:51:44 +08:00
|
|
|
|
2015-08-30 15:27:35 +08:00
|
|
|
return True
|
|
|
|
|
|
|
|
def unlock(self):
|
2015-09-29 22:51:44 +08:00
|
|
|
assert self._sock_handle is not None, "Singleton not locked"
|
|
|
|
self._sock_handle.close()
|
|
|
|
self._sock_handle = None
|
2015-08-30 15:27:35 +08:00
|
|
|
|
2017-10-01 22:59:17 +08:00
|
|
|
|
2015-08-30 15:27:35 +08:00
|
|
|
if sys.platform == "win32":
|
2015-09-29 22:51:44 +08:00
|
|
|
import winerror
|
2017-10-01 22:59:17 +08:00
|
|
|
|
2015-08-30 15:27:35 +08:00
|
|
|
SystemSingleton = WindowsSystemSingleton
|
|
|
|
else:
|
2015-09-29 22:51:44 +08:00
|
|
|
import socket
|
2017-10-01 22:59:17 +08:00
|
|
|
|
2015-08-30 15:27:35 +08:00
|
|
|
SystemSingleton = LinuxSystemSingleton
|