root/trunk/twisted/internet/error.py

Revision 34288, 10.6 KB (checked in by exarkun, 4 weeks ago)

Merge sendfiledescriptor-5615-3

Author: exarkun
Reviewer: therve
Fixes: #5615

Add an API for sending file descriptors over UNIX connections.

Line 
1# Copyright (c) Twisted Matrix Laboratories.
2# See LICENSE for details.
3
4"""
5Exceptions and errors for use in twisted.internet modules.
6"""
7
8import socket
9
10from twisted.python import deprecate
11from twisted.python.versions import Version
12
13
14
15class BindError(Exception):
16    """An error occurred binding to an interface"""
17
18    def __str__(self):
19        s = self.__doc__
20        if self.args:
21            s = '%s: %s' % (s, ' '.join(self.args))
22        s = '%s.' % s
23        return s
24
25
26
27class CannotListenError(BindError):
28    """
29    This gets raised by a call to startListening, when the object cannotstart
30    listening.
31
32    @ivar interface: the interface I tried to listen on
33    @ivar port: the port I tried to listen on
34    @ivar socketError: the exception I got when I tried to listen
35    @type socketError: L{socket.error}
36    """
37    def __init__(self, interface, port, socketError):
38        BindError.__init__(self, interface, port, socketError)
39        self.interface = interface
40        self.port = port
41        self.socketError = socketError
42
43    def __str__(self):
44        iface = self.interface or 'any'
45        return "Couldn't listen on %s:%s: %s." % (iface, self.port,
46                                                 self.socketError)
47
48
49
50class MulticastJoinError(Exception):
51    """
52    An attempt to join a multicast group failed.
53    """
54
55
56
57class MessageLengthError(Exception):
58    """Message is too long to send"""
59
60    def __str__(self):
61        s = self.__doc__
62        if self.args:
63            s = '%s: %s' % (s, ' '.join(self.args))
64        s = '%s.' % s
65        return s
66
67
68
69class DNSLookupError(IOError):
70    """DNS lookup failed"""
71
72    def __str__(self):
73        s = self.__doc__
74        if self.args:
75            s = '%s: %s' % (s, ' '.join(self.args))
76        s = '%s.' % s
77        return s
78
79
80
81class ConnectInProgressError(Exception):
82    """A connect operation was started and isn't done yet."""
83
84
85# connection errors
86
87class ConnectError(Exception):
88    """An error occurred while connecting"""
89
90    def __init__(self, osError=None, string=""):
91        self.osError = osError
92        Exception.__init__(self, string)
93
94    def __str__(self):
95        s = self.__doc__ or self.__class__.__name__
96        if self.osError:
97            s = '%s: %s' % (s, self.osError)
98        if self.args[0]:
99            s = '%s: %s' % (s, self.args[0])
100        s = '%s.' % s
101        return s
102
103
104
105class ConnectBindError(ConnectError):
106    """Couldn't bind"""
107
108
109
110class UnknownHostError(ConnectError):
111    """Hostname couldn't be looked up"""
112
113
114
115class NoRouteError(ConnectError):
116    """No route to host"""
117
118
119
120class ConnectionRefusedError(ConnectError):
121    """Connection was refused by other side"""
122
123
124
125class TCPTimedOutError(ConnectError):
126    """TCP connection timed out"""
127
128
129
130class BadFileError(ConnectError):
131    """File used for UNIX socket is no good"""
132
133
134
135class ServiceNameUnknownError(ConnectError):
136    """Service name given as port is unknown"""
137
138
139
140class UserError(ConnectError):
141    """User aborted connection"""
142
143
144
145class TimeoutError(UserError):
146    """User timeout caused connection failure"""
147
148
149
150class SSLError(ConnectError):
151    """An SSL error occurred"""
152
153
154
155class VerifyError(Exception):
156    """Could not verify something that was supposed to be signed.
157    """
158
159
160
161class PeerVerifyError(VerifyError):
162    """The peer rejected our verify error.
163    """
164
165
166
167class CertificateError(Exception):
168    """
169    We did not find a certificate where we expected to find one.
170    """
171
172
173
174try:
175    import errno
176    errnoMapping = {
177        errno.ENETUNREACH: NoRouteError,
178        errno.ECONNREFUSED: ConnectionRefusedError,
179        errno.ETIMEDOUT: TCPTimedOutError,
180    }
181    if hasattr(errno, "WSAECONNREFUSED"):
182        errnoMapping[errno.WSAECONNREFUSED] = ConnectionRefusedError
183        errnoMapping[errno.WSAENETUNREACH] = NoRouteError
184except ImportError:
185    errnoMapping = {}
186
187
188
189def getConnectError(e):
190    """Given a socket exception, return connection error."""
191    try:
192        number, string = e
193    except ValueError:
194        return ConnectError(string=e)
195
196    if hasattr(socket, 'gaierror') and isinstance(e, socket.gaierror):
197        # only works in 2.2
198        klass = UnknownHostError
199    else:
200        klass = errnoMapping.get(number, ConnectError)
201    return klass(number, string)
202
203
204
205class ConnectionClosed(Exception):
206    """
207    Connection was closed, whether cleanly or non-cleanly.
208    """
209
210
211
212class ConnectionLost(ConnectionClosed):
213    """Connection to the other side was lost in a non-clean fashion"""
214
215    def __str__(self):
216        s = self.__doc__
217        if self.args:
218            s = '%s: %s' % (s, ' '.join(self.args))
219        s = '%s.' % s
220        return s
221
222
223
224class ConnectionAborted(ConnectionLost):
225    """
226    Connection was aborted locally, using
227    L{twisted.internet.interfaces.ITCPTransport.abortConnection}.
228
229    @since: 11.1
230    """
231
232
233
234class ConnectionDone(ConnectionClosed):
235    """Connection was closed cleanly"""
236
237    def __str__(self):
238        s = self.__doc__
239        if self.args:
240            s = '%s: %s' % (s, ' '.join(self.args))
241        s = '%s.' % s
242        return s
243
244
245
246class FileDescriptorOverrun(ConnectionLost):
247    """
248    A mis-use of L{IUNIXTransport.sendFileDescriptor} caused the connection to
249    be closed.
250
251    Each file descriptor sent using C{sendFileDescriptor} must be associated
252    with at least one byte sent using L{ITransport.write}.  If at any point
253    fewer bytes have been written than file descriptors have been sent, the
254    connection is closed with this exception.
255    """
256
257
258
259class ConnectionFdescWentAway(ConnectionLost):
260    """Uh""" #TODO
261
262
263
264class AlreadyCalled(ValueError):
265    """Tried to cancel an already-called event"""
266
267    def __str__(self):
268        s = self.__doc__
269        if self.args:
270            s = '%s: %s' % (s, ' '.join(self.args))
271        s = '%s.' % s
272        return s
273
274
275
276class AlreadyCancelled(ValueError):
277    """Tried to cancel an already-cancelled event"""
278
279    def __str__(self):
280        s = self.__doc__
281        if self.args:
282            s = '%s: %s' % (s, ' '.join(self.args))
283        s = '%s.' % s
284        return s
285
286
287
288class PotentialZombieWarning(Warning):
289    """
290    Emitted when L{IReactorProcess.spawnProcess} is called in a way which may
291    result in termination of the created child process not being reported.
292
293    Deprecated in Twisted 10.0.
294    """
295    MESSAGE = (
296        "spawnProcess called, but the SIGCHLD handler is not "
297        "installed. This probably means you have not yet "
298        "called reactor.run, or called "
299        "reactor.run(installSignalHandler=0). You will probably "
300        "never see this process finish, and it may become a "
301        "zombie process.")
302
303deprecate.deprecatedModuleAttribute(
304    Version("Twisted", 10, 0, 0),
305    "There is no longer any potential for zombie process.",
306    __name__,
307    "PotentialZombieWarning")
308
309
310
311class ProcessDone(ConnectionDone):
312    """A process has ended without apparent errors"""
313
314    def __init__(self, status):
315        Exception.__init__(self, "process finished with exit code 0")
316        self.exitCode = 0
317        self.signal = None
318        self.status = status
319
320
321
322class ProcessTerminated(ConnectionLost):
323    """A process has ended with a probable error condition"""
324
325    def __init__(self, exitCode=None, signal=None, status=None):
326        self.exitCode = exitCode
327        self.signal = signal
328        self.status = status
329        s = "process ended"
330        if exitCode is not None: s = s + " with exit code %s" % exitCode
331        if signal is not None: s = s + " by signal %s" % signal
332        Exception.__init__(self, s)
333
334
335
336class ProcessExitedAlready(Exception):
337    """
338    The process has already exited and the operation requested can no longer
339    be performed.
340    """
341
342
343
344class NotConnectingError(RuntimeError):
345    """The Connector was not connecting when it was asked to stop connecting"""
346
347    def __str__(self):
348        s = self.__doc__
349        if self.args:
350            s = '%s: %s' % (s, ' '.join(self.args))
351        s = '%s.' % s
352        return s
353
354
355
356class NotListeningError(RuntimeError):
357    """The Port was not listening when it was asked to stop listening"""
358
359    def __str__(self):
360        s = self.__doc__
361        if self.args:
362            s = '%s: %s' % (s, ' '.join(self.args))
363        s = '%s.' % s
364        return s
365
366
367
368class ReactorNotRunning(RuntimeError):
369    """
370    Error raised when trying to stop a reactor which is not running.
371    """
372
373
374class ReactorNotRestartable(RuntimeError):
375    """
376    Error raised when trying to run a reactor which was stopped.
377    """
378
379
380
381class ReactorAlreadyRunning(RuntimeError):
382    """
383    Error raised when trying to start the reactor multiple times.
384    """
385
386
387class ReactorAlreadyInstalledError(AssertionError):
388    """
389    Could not install reactor because one is already installed.
390    """
391
392
393
394class ConnectingCancelledError(Exception):
395    """
396    An C{Exception} that will be raised when an L{IStreamClientEndpoint} is
397    cancelled before it connects.
398
399    @ivar address: The L{IAddress} that is the destination of the
400        cancelled L{IStreamClientEndpoint}.
401    """
402
403    def __init__(self, address):
404        """
405        @param address: The L{IAddress} that is the destination of the
406            L{IStreamClientEndpoint} that was cancelled.
407        """
408        Exception.__init__(self, address)
409        self.address = address
410
411
412
413class UnsupportedAddressFamily(Exception):
414    """
415    An attempt was made to use a socket with an address family (eg I{AF_INET},
416    I{AF_INET6}, etc) which is not supported by the reactor.
417    """
418
419
420
421class UnsupportedSocketType(Exception):
422    """
423    An attempt was made to use a socket of a type (eg I{SOCK_STREAM},
424    I{SOCK_DGRAM}, etc) which is not supported by the reactor.
425    """
426
427
428class AlreadyListened(Exception):
429    """
430    An attempt was made to listen on a file descriptor which can only be
431    listened on once.
432    """
433
434
435__all__ = [
436    'BindError', 'CannotListenError', 'MulticastJoinError',
437    'MessageLengthError', 'DNSLookupError', 'ConnectInProgressError',
438    'ConnectError', 'ConnectBindError', 'UnknownHostError', 'NoRouteError',
439    'ConnectionRefusedError', 'TCPTimedOutError', 'BadFileError',
440    'ServiceNameUnknownError', 'UserError', 'TimeoutError', 'SSLError',
441    'VerifyError', 'PeerVerifyError', 'CertificateError',
442    'getConnectError', 'ConnectionClosed', 'ConnectionLost',
443    'ConnectionDone', 'ConnectionFdescWentAway', 'AlreadyCalled',
444    'AlreadyCancelled', 'PotentialZombieWarning', 'ProcessDone',
445    'ProcessTerminated', 'ProcessExitedAlready', 'NotConnectingError',
446    'NotListeningError', 'ReactorNotRunning', 'ReactorAlreadyRunning',
447    'ReactorAlreadyInstalledError', 'ConnectingCancelledError',
448    'UnsupportedAddressFamily', 'UnsupportedSocketType']
Note: See TracBrowser for help on using the browser.