GrimReaper.on_connection_error()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 0
loc 2
rs 10
1
#!/usr/bin/env python
2
# coding: utf-8
3
import logging
4
import os
5
import socket
6
7
__version__ = '0.1'
8
9
log = logging.getLogger(__name__)
10
11
12
class GrimReaper(object):
13
    def __init__(self, socket_path='/tmp/GrimReaper.socket', process_timeout=30):
14
        self._path = socket_path
15
        self._process_timeout = process_timeout
16
        self._connect()
17
18
    def _is_connected(self):
19
        try:
20
            self._socket.recv(0)
21
        except socket.error as e:
22
            if e.errno == socket.errno.EAGAIN:
23
                return True
24
            else:
25
                log.debug(e)
26
                return self._connect()
27
        else:
28
            log.debug('Connection is active')
29
            return True
30
31
    def _connect(self):
32
        self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
33
        self._socket.setblocking(0)
34
35
        try:
36
            self._socket.connect(self._path)
37
        except socket.error as e:
38
            # Transport endpoint is already connected
39
            if e.errno == 106:
40
                return True
41
42
            log.error('Unable to connect to the socket "%s": %s', self._path, e)
43
            self.on_connection_error(e)
44
45
            if e.errno == socket.errno.ENOENT:
46
                # No such file or directory
47
                return False
48
            elif e.errno == socket.errno.ECONNREFUSED:
49
                # Connection refused
50
                return False
51
            elif e.errno == socket.errno.EPIPE:
52
                # Broken pipe
53
                return False
54
55
            raise
56
        return True
57
58
    def _close(self):
59
        self._socket.close()
60
61 View Code Duplication
    def register(self, timeout=None, pid=None):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
62
        if timeout is None:
63
            timeout = self._process_timeout
64
65
        if pid is None:
66
            pid = os.getpid()
67
68
        if self._is_connected():
69
            msg = 'register:%s:%s' % (pid, timeout)
70
            try:
71
                self._socket.sendall(msg.encode('utf-8'))
72
            except socket.error as e:
73
                if e.errno == socket.errno.EPIPE:
74
                    self._close()
75
                    return
76
                log.debug(e)
77
78
            log.debug('Registered process (PID=%s; timeout=%s)', pid, timeout)
79
        else:
80
            log.warning('Unable to register the process (PID=%s).', pid)
81
82 View Code Duplication
    def unregister(self, pid=None):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
83
        if pid is None:
84
            pid = os.getpid()
85
86
        if self._is_connected():
87
            msg = 'unregister:%s' % pid
88
            try:
89
                self._socket.sendall(msg.encode('utf-8'))
90
            except socket.error as e:
91
                if e.errno == socket.errno.EPIPE:
92
                    self._close()
93
                    return
94
                log.debug(e)
95
96
            log.debug('Unregistered process (PID=%s)', pid)
97
        else:
98
            log.warning('Unable to unregister the process (PID=%s).', pid)
99
100
    def on_connection_error(self, exc):
101
        pass
102