1 """
2 A simple module for acquiring pidfile locks (e.g., for use by daemons).
3
4 Copyright (C) 2010 by Peter F. Couvares, Syracuse University
5 mailto: pfcouvar@syr.edu
6 """
7
8 from __future__ import print_function
9 import os
10 import sys
11 import errno
12 import fcntl
13 import time
14
15 import glue.utils
16
17
18
19
20
21
22
23
24
26 """
27 Tries to write a lockfile containing the current pid. Excepts if
28 the lockfile already contains the pid of a running process.
29
30 Although this should prevent a lock from being granted twice, it
31 can theoretically deny a lock unjustly in the unlikely event that
32 the original process is gone but another unrelated process has
33 been assigned the same pid by the OS.
34 """
35
36 pidfile = open(lockfile, "a+")
37
38
39
40
41 try:
42 fcntl.flock(pidfile.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB)
43 except IOError as e:
44 raise RuntimeError("failed to lock %s: %s" % (lockfile, e))
45
46
47 pidfile.seek(0)
48 pidfile_pid = pidfile.readline().strip()
49
50 if pidfile_pid.isdigit():
51 if glue.utils.pid_exists(int(pidfile_pid)):
52 raise RuntimeError("pidfile %s contains pid (%s) of a running "
53 "process" % (lockfile, pidfile_pid))
54 else:
55 print ("pidfile %s contains stale pid %s; writing new lock" %
56 (lockfile, pidfile_pid))
57
58
59 pidfile.truncate(0)
60 pidfile.write("%d\n" % os.getpid())
61 pidfile.close()
62
63
64 confirm_lock(lockfile)
65 return True
66
67
69 """
70 Confirm that the given lockfile contains our pid.
71 Should be entirely unecessary, but paranoia always served me well.
72 """
73 pidfile = open(lockfile, "r")
74 pidfile_pid = pidfile.readline().strip()
75 pidfile.close()
76 if int(pidfile_pid) != os.getpid():
77 raise RuntimeError("pidfile %s contains pid %s; expected pid %s!" %
78 (lockfile, os.getpid(), pidfile_pid))
79 return True
80