]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/orchestrator: Use `pickle` to pass exceptions across sub-interpreters 33179/head
authorSebastian Wagner <sebastian.wagner@suse.com>
Mon, 10 Feb 2020 13:20:25 +0000 (14:20 +0100)
committerSebastian Wagner <sebastian.wagner@suse.com>
Mon, 10 Feb 2020 13:20:25 +0000 (14:20 +0100)
`copy.deepcopy` doesn't work to cross sub-interpreter boundaries.

Fixes: https://tracker.ceph.com/issues/43913
Signed-off-by: Sebastian Wagner <sebastian.wagner@suse.com>
src/pybind/mgr/orchestrator.py

index a295f42c3aaa0e88fc51552bbca1cae1837489eb..01409ccb07ce93a6b19d85192628d46e9b30c2db 100644 (file)
@@ -7,6 +7,7 @@ Please see the ceph-mgr module developer's guide for more information.
 import copy
 import functools
 import logging
+import pickle
 import sys
 import time
 from collections import namedtuple
@@ -202,6 +203,23 @@ class _Promise(object):
         # T instead of (T -> r) -> r. Therefore we need to store the first promise here.
         self._first_promise = _first_promise or self  # type: '_Promise'
 
+    @property
+    def _exception(self):
+        # type: () -> Optional[Exception]
+        return getattr(self, '_exception_', None)
+
+    @_exception.setter
+    def _exception(self, e):
+        self._exception_ = e
+        self._serialized_exception_ = pickle.dumps(e) if e is not None else None
+
+    @property
+    def _serialized_exception(self):
+        # type: () -> Optional[bytes]
+        return getattr(self, '_serialized_exception_', None)
+
+
+
     @property
     def _on_complete(self):
         # type: () -> Optional[Callable]
@@ -568,6 +586,11 @@ class Completion(_Promise):
         # type: () -> Optional[Exception]
         return self._last_promise()._exception
 
+    @property
+    def serialized_exception(self):
+        # type: () -> Optional[bytes]
+        return self._last_promise()._serialized_exception
+
     @property
     def has_result(self):
         # type: () -> bool
@@ -631,9 +654,9 @@ def raise_if_exception(c):
     :raises OrchestratorError: Some user error or a config error.
     :raises Exception: Some internal error
     """
-    if c.exception is not None:
+    if c.serialized_exception is not None:
         try:
-            e = copy.deepcopy(c.exception)
+            e = pickle.loads(c.serialized_exception)
         except (KeyError, AttributeError):
             raise Exception('{}: {}'.format(type(c.exception), c.exception))
         raise e