forked from goodboy/tractor
				
			Always raise remote (cancelled) error if set
Previously we weren't raising a remote error if the local scope was cancelled during a call to `Context.result()` which is problematic if the caller WAS NOT the requester for said remote cancellation; in that case we still want a `ContextCancelled` raised with the `.canceller: str` set to the cancelling actor uid. Further fix a naming bug where the (seemingly older) `._remote_err` was being set to such an error instead of `._remote_error` XDmultihomed
							parent
							
								
									919e462f88
								
							
						
					
					
						commit
						575a24adf1
					
				|  | @ -102,10 +102,14 @@ class Context: | ||||||
|     _remote_error: BaseException | None = None |     _remote_error: BaseException | None = None | ||||||
| 
 | 
 | ||||||
|     # cancellation state |     # cancellation state | ||||||
|     _cancel_called: bool = False |     _cancel_called: bool = False  # did WE cancel the far end? | ||||||
|     _cancelled_remote: tuple | None = None |     _cancelled_remote: tuple[str, str] | None = None | ||||||
|     _cancel_msg: str | None = None |     _cancel_msg: str | None = None | ||||||
|     _scope: trio.CancelScope | None = None |     _scope: trio.CancelScope | None = None | ||||||
|  | 
 | ||||||
|  |     # NOTE:  this is set by the `.devx._debug` machinery | ||||||
|  |     # to indicate whether code in `._runtime` should handle | ||||||
|  |     # cancelled context crashes in the pdbp REPL. | ||||||
|     _enter_debugger_on_cancel: bool = True |     _enter_debugger_on_cancel: bool = True | ||||||
| 
 | 
 | ||||||
|     @property |     @property | ||||||
|  | @ -207,7 +211,7 @@ class Context: | ||||||
|         # XXX: set the remote side's error so that after we cancel |         # XXX: set the remote side's error so that after we cancel | ||||||
|         # whatever task is the opener of this context it can raise |         # whatever task is the opener of this context it can raise | ||||||
|         # that error as the reason. |         # that error as the reason. | ||||||
|         self._remote_error = error |         self._remote_error: BaseException = error | ||||||
| 
 | 
 | ||||||
|         # always record the remote actor's uid since its cancellation |         # always record the remote actor's uid since its cancellation | ||||||
|         # state is directly linked to ours (the local one). |         # state is directly linked to ours (the local one). | ||||||
|  | @ -488,11 +492,7 @@ class Context: | ||||||
|         assert self._portal, "Context.result() can not be called from callee!" |         assert self._portal, "Context.result() can not be called from callee!" | ||||||
|         assert self._recv_chan |         assert self._recv_chan | ||||||
| 
 | 
 | ||||||
|         # from . import _debug |         if re := self._remote_error: | ||||||
|         # await _debug.breakpoint() |  | ||||||
| 
 |  | ||||||
|         re = self._remote_error |  | ||||||
|         if re: |  | ||||||
|             self._maybe_raise_remote_err(re) |             self._maybe_raise_remote_err(re) | ||||||
|             return re |             return re | ||||||
| 
 | 
 | ||||||
|  | @ -507,7 +507,7 @@ class Context: | ||||||
|             while True: |             while True: | ||||||
|                 msg = await self._recv_chan.receive() |                 msg = await self._recv_chan.receive() | ||||||
|                 try: |                 try: | ||||||
|                     self._result = msg['return'] |                     self._result: Any = msg['return'] | ||||||
| 
 | 
 | ||||||
|                     # NOTE: we don't need to do this right? |                     # NOTE: we don't need to do this right? | ||||||
|                     # XXX: only close the rx mem chan AFTER |                     # XXX: only close the rx mem chan AFTER | ||||||
|  | @ -516,6 +516,21 @@ class Context: | ||||||
|                     #     await self._recv_chan.aclose() |                     #     await self._recv_chan.aclose() | ||||||
| 
 | 
 | ||||||
|                     break |                     break | ||||||
|  | 
 | ||||||
|  |                 # NOTE: we get here if the far end was | ||||||
|  |                 # `ContextCancelled` in 2 cases: | ||||||
|  |                 # - we requested the cancellation and thus | ||||||
|  |                 #   SHOULD NOT raise that far end error, | ||||||
|  |                 # - WE DID NOT REQUEST that cancel and thus | ||||||
|  |                 #   SHOULD RAISE HERE! | ||||||
|  |                 except trio.Cancelled: | ||||||
|  |                     if not self._cancel_called: | ||||||
|  |                         raise self._remote_error | ||||||
|  |                     else: | ||||||
|  |                         # if we DID request the cancel we simply | ||||||
|  |                         # continue as normal. | ||||||
|  |                         raise | ||||||
|  | 
 | ||||||
|                 except KeyError:  # as msgerr: |                 except KeyError:  # as msgerr: | ||||||
| 
 | 
 | ||||||
|                     if 'yield' in msg: |                     if 'yield' in msg: | ||||||
|  | @ -537,7 +552,7 @@ class Context: | ||||||
|                     )  # from msgerr |                     )  # from msgerr | ||||||
| 
 | 
 | ||||||
|                     err = self._maybe_raise_remote_err(err) |                     err = self._maybe_raise_remote_err(err) | ||||||
|                     self._remote_err = err |                     self._remote_error = err | ||||||
| 
 | 
 | ||||||
|         return self._remote_error or self._result |         return self._remote_error or self._result | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue