_baseprocess.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. # -*- test-case-name: twisted.test.test_process -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. """
  5. Cross-platform process-related functionality used by different
  6. L{IReactorProcess} implementations.
  7. """
  8. from twisted.python.reflect import qual
  9. from twisted.python.deprecate import getWarningMethod
  10. from twisted.python.failure import Failure
  11. from twisted.python.log import err
  12. _missingProcessExited = ("Since Twisted 8.2, IProcessProtocol.processExited "
  13. "is required. %s must implement it.")
  14. class BaseProcess(object):
  15. pid = None
  16. status = None
  17. lostProcess = 0
  18. proto = None
  19. def __init__(self, protocol):
  20. self.proto = protocol
  21. def _callProcessExited(self, reason):
  22. default = object()
  23. processExited = getattr(self.proto, 'processExited', default)
  24. if processExited is default:
  25. getWarningMethod()(
  26. _missingProcessExited % (qual(self.proto.__class__),),
  27. DeprecationWarning, stacklevel=0)
  28. else:
  29. try:
  30. processExited(Failure(reason))
  31. except:
  32. err(None, "unexpected error in processExited")
  33. def processEnded(self, status):
  34. """
  35. This is called when the child terminates.
  36. """
  37. self.status = status
  38. self.lostProcess += 1
  39. self.pid = None
  40. self._callProcessExited(self._getReason(status))
  41. self.maybeCallProcessEnded()
  42. def maybeCallProcessEnded(self):
  43. """
  44. Call processEnded on protocol after final cleanup.
  45. """
  46. if self.proto is not None:
  47. reason = self._getReason(self.status)
  48. proto = self.proto
  49. self.proto = None
  50. try:
  51. proto.processEnded(Failure(reason))
  52. except:
  53. err(None, "unexpected error in processEnded")