~gary/tarmac/fix693595

« back to all changes in this revision

Viewing changes to tarmac/pidfile.py

  • Committer: Gary Poster
  • Date: 2010-12-23 18:28:32 UTC
  • Revision ID: gary.poster@canonical.com-20101223182832-t8fiby7u45rjo3be
fix bug 693595 by making commit plugins able to cancel a merge.  Correct some logic errors along the way, revealed by this work.

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
 
8
8
import tempfile
9
9
import os
 
10
import time
10
11
import atexit
11
12
import sys
12
13
from signal import signal, SIGTERM
14
15
from tarmac.config import TarmacConfig
15
16
 
16
17
 
 
18
class PidfileExistsError(RuntimeError):
 
19
    def __init__(self, pidfile, pid, lifetime):
 
20
        self.pidfile = pidfile
 
21
        self.pid = pid
 
22
        self.lifetime = lifetime
 
23
 
 
24
    def __str__(self):
 
25
        return (
 
26
            'File %r reports that PID %r has existed for %d seconds' % (
 
27
                self.pidfile, self.pid, self.lifetime))
 
28
 
17
29
def make_pidfile():
18
30
    """Write the current process id to a PID file.
19
31
 
24
36
    inside it.
25
37
    """
26
38
    pidfile = TarmacConfig().PID_FILE
27
 
    if os.path.exists(pidfile):
28
 
        raise RuntimeError("PID file %s already exists. Already running?" %
29
 
                pidfile)
30
 
 
31
 
    atexit.register(remove_pidfile)
32
 
    def remove_pidfile_handler(*ignored):
33
 
        sys.exit(-1 * SIGTERM)
34
 
    signal(SIGTERM, remove_pidfile_handler)
35
 
 
36
39
    fd, tempname = tempfile.mkstemp(dir=os.path.dirname(pidfile))
37
40
    outf = os.fdopen(fd, 'w')
38
41
    outf.write(str(os.getpid())+'\n')
39
42
    outf.flush()
40
43
    outf.close()
41
 
    os.rename(tempname, pidfile)
 
44
    # This introduces a race condition.  We're hoping it doesn't happen.
 
45
    if os.path.exists(pidfile):
 
46
        os.remove(tempname)
 
47
        raise PidfileExistsError(tempname, get_pid(), get_pidfile_lifetime())
 
48
    else:
 
49
        os.rename(tempname, pidfile)
 
50
 
 
51
 
 
52
# This could be used if the pidfile creation were not within a loop.
 
53
#
 
54
# def install_pidfile_removal():
 
55
#
 
56
#    atexit.register(remove_pidfile)
 
57
#    def remove_pidfile_handler(*ignored):
 
58
#        sys.exit(-1 * SIGTERM)
 
59
#    signal(SIGTERM, remove_pidfile_handler)
42
60
 
43
61
 
44
62
def remove_pidfile():
73
91
    except IOError:
74
92
        return None
75
93
    except ValueError:
76
 
        raise ValueError("Invalid PID %s" % repr(pid))
77
 
 
 
94
        raise ValueError("Invalid PID %r" % pid)
 
95
 
 
96
 
 
97
def get_pidfile_lifetime():
 
98
    """Return the number of seconds since the pidfile was created"""
 
99
    creation_time = os.stat(TarmacConfig().PID_FILE)[-1]
 
100
    now = time.time()
 
101
    return now - creation_time