This repository has been archived on 2024-12-26. You can view files and clone it, but cannot push or open issues or pull requests.
PyBitmessage-2024-12-26/src/singleton.py
Peter Surda 4865659d72
Main process fixes
- handles old dialog versions better if using curses
- can spawn SMTP delivery thread if configured (only when in daemon
  mode)
- daemonized mode now works more like it's properly supposed to on unix
  (double fork etc). You may have to adjust your init scripts, when
  when using upstart for example you should now use "expect daemon"
- daemon mode now cleanly shuts down when TERM/INT signal is received
2016-06-30 12:30:05 +02:00

75 lines
2.5 KiB
Python

#! /usr/bin/env python
import atexit
import errno
from multiprocessing import Process
import os
import sys
import shared
try:
import fcntl # @UnresolvedImport
except:
pass
class singleinstance:
"""
Implements a single instance application by creating a lock file at appdata.
This is based upon the singleton class from tendo https://github.com/pycontribs/tendo
which is under the Python Software Foundation License version 2
"""
def __init__(self, flavor_id="", daemon=False):
self.initialized = False
self.counter = 0
self.daemon = daemon
self.lockfile = os.path.normpath(os.path.join(shared.appdata, 'singleton%s.lock' % flavor_id))
if not self.daemon and not shared.curses:
# Tells the already running (if any) application to get focus.
import bitmessageqt
bitmessageqt.init()
if sys.platform == 'win32':
try:
# file already exists, we try to remove (in case previous execution was interrupted)
if os.path.exists(self.lockfile):
os.unlink(self.lockfile)
self.fd = os.open(self.lockfile, os.O_CREAT | os.O_EXCL | os.O_RDWR)
except OSError:
type, e, tb = sys.exc_info()
if e.errno == 13:
print 'Another instance of this application is already running'
sys.exit(-1)
print(e.errno)
raise
else: # non Windows
self.fp = open(self.lockfile, 'w')
try:
fcntl.lockf(self.fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError:
print 'Another instance of this application is already running'
sys.exit(-1)
self.initialized = True
atexit.register(self.cleanup)
def cleanup(self):
if not self.initialized:
return
self.counter += 1
if self.daemon and self.counter < 3:
# these are the two initial forks while daemonizing
return
print "Cleaning up lockfile"
try:
if sys.platform == 'win32':
if hasattr(self, 'fd'):
os.close(self.fd)
os.unlink(self.lockfile)
else:
fcntl.lockf(self.fp, fcntl.LOCK_UN)
if os.path.isfile(self.lockfile):
os.unlink(self.lockfile)
except Exception, e:
pass