~ubuntu-branches/ubuntu/trusty/ceilometer/trusty-proposed

« back to all changes in this revision

Viewing changes to ceilometer/openstack/common/service.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, James Page, Chuck Short
  • Date: 2014-01-23 15:08:11 UTC
  • mfrom: (1.1.11)
  • Revision ID: package-import@ubuntu.com-20140123150811-1zaismsuyh1hcl8y
Tags: 2014.1~b2-0ubuntu1
[ James Page ]
* d/control: Add python-jsonpath-rw to BD's.
* d/p/fix-setup-requirements.patch: Bump WebOb to support < 1.4.
 (LP: #1261101)

[ Chuck Short ]
* New upstream version.
* debian/control, debian/ceilometer-common.install: Split out
  ceilometer-alarm-evaluator and ceilometer-alarm-notifier into their
  own packages. (LP: #1250002)
* debian/ceilometer-agent-central.logrotate,
  debian/ceilometer-agent-compute.logrotate,
  debian/ceilometer-api.logrotate,
  debian/ceilometer-collector.logrotate: Add logrotate files, 
  thanks to Ahmed Rahal. (LP: #1224223)
* Fix typos in upstart files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
import random
24
24
import signal
25
25
import sys
 
26
import threading
26
27
import time
27
28
 
 
29
try:
 
30
    # Importing just the symbol here because the io module does not
 
31
    # exist in Python 2.6.
 
32
    from io import UnsupportedOperation  # noqa
 
33
except ImportError:
 
34
    # Python 2.6
 
35
    UnsupportedOperation = None
 
36
 
28
37
import eventlet
29
 
from eventlet import event
30
38
from oslo.config import cfg
31
39
 
32
40
from ceilometer.openstack.common import eventlet_backdoor
33
 
from ceilometer.openstack.common.gettextutils import _  # noqa
 
41
from ceilometer.openstack.common.gettextutils import _
34
42
from ceilometer.openstack.common import importutils
35
43
from ceilometer.openstack.common import log as logging
36
44
from ceilometer.openstack.common import threadgroup
45
53
    return hasattr(signal, 'SIGHUP')
46
54
 
47
55
 
48
 
def _is_sighup(signo):
49
 
    return _sighup_supported() and signo == signal.SIGHUP
 
56
def _is_daemon():
 
57
    # The process group for a foreground process will match the
 
58
    # process group of the controlling terminal. If those values do
 
59
    # not match, or ioctl() fails on the stdout file handle, we assume
 
60
    # the process is running in the background as a daemon.
 
61
    # http://www.gnu.org/software/bash/manual/bashref.html#Job-Control-Basics
 
62
    try:
 
63
        is_daemon = os.getpgrp() != os.tcgetpgrp(sys.stdout.fileno())
 
64
    except OSError as err:
 
65
        if err.errno == errno.ENOTTY:
 
66
            # Assume we are a daemon because there is no terminal.
 
67
            is_daemon = True
 
68
        else:
 
69
            raise
 
70
    except UnsupportedOperation:
 
71
        # Could not get the fileno for stdout, so we must be a daemon.
 
72
        is_daemon = True
 
73
    return is_daemon
 
74
 
 
75
 
 
76
def _is_sighup_and_daemon(signo):
 
77
    if not (_sighup_supported() and signo == signal.SIGHUP):
 
78
        # Avoid checking if we are a daemon, because the signal isn't
 
79
        # SIGHUP.
 
80
        return False
 
81
    return _is_daemon()
50
82
 
51
83
 
52
84
def _signo_to_signame(signo):
160
192
        while True:
161
193
            self.handle_signal()
162
194
            status, signo = self._wait_for_exit_or_signal(ready_callback)
163
 
            if not _is_sighup(signo):
 
195
            if not _is_sighup_and_daemon(signo):
164
196
                return status
165
197
            self.restart()
166
198
 
174
206
 
175
207
 
176
208
class ProcessLauncher(object):
177
 
    def __init__(self):
 
209
    def __init__(self, wait_interval=0.01):
 
210
        """Constructor.
 
211
 
 
212
        :param wait_interval: The interval to sleep for between checks
 
213
                              of child process exit.
 
214
        """
178
215
        self.children = {}
179
216
        self.sigcaught = None
180
217
        self.running = True
 
218
        self.wait_interval = wait_interval
181
219
        rfd, self.writepipe = os.pipe()
182
220
        self.readpipe = eventlet.greenio.GreenPipe(rfd, 'r')
183
221
        self.handle_signal()
280
318
            while True:
281
319
                self._child_process_handle_signal()
282
320
                status, signo = self._child_wait_for_exit_or_signal(launcher)
283
 
                if not _is_sighup(signo):
 
321
                if not _is_sighup_and_daemon(signo):
284
322
                    break
285
323
                launcher.restart()
286
324
 
335
373
                # Yield to other threads if no children have exited
336
374
                # Sleep for a short time to avoid excessive CPU usage
337
375
                # (see bug #1095346)
338
 
                eventlet.greenthread.sleep(.01)
 
376
                eventlet.greenthread.sleep(self.wait_interval)
339
377
                continue
340
378
            while self.running and len(wrap.children) < wrap.workers:
341
379
                self._start_child(wrap)
352
390
            if self.sigcaught:
353
391
                signame = _signo_to_signame(self.sigcaught)
354
392
                LOG.info(_('Caught %s, stopping children'), signame)
355
 
            if not _is_sighup(self.sigcaught):
 
393
            if not _is_sighup_and_daemon(self.sigcaught):
356
394
                break
357
395
 
358
396
            for pid in self.children:
381
419
        self.tg = threadgroup.ThreadGroup(threads)
382
420
 
383
421
        # signal that the service is done shutting itself down:
384
 
        self._done = event.Event()
 
422
        self._done = threading.Event()
385
423
 
386
424
    def reset(self):
387
 
        # NOTE(Fengqian): docs for Event.reset() recommend against using it
388
 
        self._done = event.Event()
 
425
        self._done = threading.Event()
389
426
 
390
427
    def start(self):
391
428
        pass
394
431
        self.tg.stop()
395
432
        self.tg.wait()
396
433
        # Signal that service cleanup is done:
397
 
        if not self._done.ready():
398
 
            self._done.send()
 
434
        self._done.set()
399
435
 
400
436
    def wait(self):
401
437
        self._done.wait()
406
442
    def __init__(self):
407
443
        self.services = []
408
444
        self.tg = threadgroup.ThreadGroup()
409
 
        self.done = event.Event()
 
445
        self.done = threading.Event()
410
446
 
411
447
    def add(self, service):
412
448
        self.services.append(service)
420
456
 
421
457
        # Each service has performed cleanup, now signal that the run_service
422
458
        # wrapper threads can now die:
423
 
        if not self.done.ready():
424
 
            self.done.send()
 
459
        self.done.set()
425
460
 
426
461
        # reap threads:
427
462
        self.tg.stop()
431
466
 
432
467
    def restart(self):
433
468
        self.stop()
434
 
        self.done = event.Event()
 
469
        self.done = threading.Event()
435
470
        for restart_service in self.services:
436
471
            restart_service.reset()
437
472
            self.tg.add_thread(self.run_service, restart_service, self.done)