error.py 13 KB

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