Commit 2cb541c1 authored by Daniel Armbruster's avatar Daniel Armbruster Committed by thomas.forbriger
Browse files

pidhandler implemented and tested.

This is a legacy commit from before 2015-05-18.
It may be incomplete as well as inconsistent.
See COPYING.legacy and README.history for details.

The pidhandler class uses a lockfile mechanism to check for running processes.


SVN Path:     http://gpitrsvn.gpi.uni-karlsruhe.de/repos/TFSoftware/trunk
SVN Revision: 4335
SVN UUID:     67feda4a-a26e-11df-9d6e-31afc202ad0c
parent 8efe7ff7
#!/usr/bin/env python
## @file pidlock.py
# @brief Module which implements a pid handler which makes use of a lockfile.
#
# -----------------------------------------------------------------------------
#
# $Id$
# @author Daniel Armbruster
# \date 04/01/2012
#
# Purpose: Module which implements a pid handler which makes use of a lockfile.
#
# ----
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ----
#
# Copyright (c) 2012 by Daniel Armbruster
#
# REVISIONS and CHANGES
# 04/01/2012 V1.0 Daniel Armbruster
#
# =============================================================================
import os
import sys
import subprocess
__version__ = "V1.0"
__subversion__ = "$Id$"
__license__ = "GPLv2"
__author__ = "Daniel Armbruster"
__copyright__ = "Copyright (c) 2012 by Daniel Armbruster"
# -----------------------------------------------------------------------------
# variables
path = os.path.expanduser("~")
lockfilename = ".lock"
# -----------------------------------------------------------------------------
class PidLockError(Exception):
"""
Exception class of pidlock module.
"""
def __init__(self, line, msg):
self.msg = msg
self.line = line
def display(self):
sys.stderr.write("pidlock (ERROR): " + str(self.msg) + "\n")
sys.stderr.write("triggered in line: " + str(self.line) + "\n")
# -----------------------------------------------------------------------------
class PidHandler:
"""
Implements a handler for a pid. This handler uses a pidlockfile mechanism to
keep a log of the asserted pids.
Note that this handler does its work only on *nix platforms properly. Use
inheritance to overload the corresponding functions.
"""
def __init__(self):
self.path = os.path.join(path,lockfilename)
self.notCanceled = True
def announce(self, pid):
"""
Announce a process with pid to the handler.
"""
# remove file if pid not valid anymore
if self.__access() and not self.__pidValid():
os.remove(self.path)
# wait until pid is not valid anymore
while (self.__pidValid() and pid in PidHandler.registeredPids):
print("process [{0}] active.".format(self.__getpid()))
pass
# create a new pidlockfile
try:
pidfile = open(self.path, 'w')
pidfile.write("{0}".format(pid))
PidHandler.registeredPids.append(pid)
except IOError as err:
raise PidLockError(81, "[Errno "+str(err.errno)+"] "+err.strerror+": " \
+err.filename)
else:
pidfile.close()
def cancel(self, pid):
"""
Remove a process with pid of the handler. The process only can cancel from
the handler if the process had been announced.
"""
print("Process canceled.")
if self.__getpid() == pid:
os.remove(self.path)
PidHandler.registeredPids.remove(pid)
def __pidValid(self):
"""
Check if the process with the pid in the pid lockfile is still active.
"""
if self.__access():
pidfile = open(self.path, 'r')
pidfile.seek(0)
pid = pidfile.readline()
return self.__pidActive(pid)
return False
def __access(self):
"""
Check if there is access to a pid lockfile.
"""
return os.access(self.path, os.F_OK)
def __getpid(self):
if self.__access():
pidfile = open(self.path, 'r')
pidfile.seek(0)
pid = pidfile.readline()
return pid
def __pidActive(self, pid):
"""
True if the process with pid is still active.
Note that this function only works on *nix platforms. Overload it for other
platforms.
"""
return os.path.exists("/proc/{0}".format(pid))
registeredPids = []
# -----------------------------------------------------------------------------
# Tests
if __name__ == '__main__':
try:
# create handlers
pidhandler1 = PidHandler()
# announce pid of popen 1
popen1 = subprocess.Popen('echo "Process 1"', shell=True)
print(popen1.pid)
pidhandler1.announce(popen1.pid)
# announce another pid
popen2 = subprocess.Popen('echo "Process 2"', shell=True)
print(popen2.pid)
pidhandler1.announce(popen2.pid)
pidhandler1.cancel(popen1.pid)
popen1.kill()
except PidLockError as err:
err.display()
sys.exit()
# ----- END OF pidlock.py -----
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment