cyx-6 opened a new pull request, #709:
URL: https://github.com/apache/tvm-ffi/pull/709
## Motivation
`Error.py_error()` attaches the FFI error object to the Python exception it
raises:
```python
py_error.__tvm_ffi_error__ = self
```
`BaseException.__reduce__` includes the instance `__dict__`, so pickling an
FFI-originated exception pickles that `Error` through `CObject.__getstate__` →
`ToJSONGraph`. `ffi.Error` has no native creator and no `__ffi_new__` type
attr, so this fails:
```
TypeError: Type `ffi.Error` does not support ToJSONGraph
(no native creator or __ffi_new__ type attr)
```
Harnesses that ship exceptions across a process boundary lose the original
error and report this instead. It was reported downstream against a CUDA IMA
(error 700), where the replacement message made it look like tvm-ffi had
suppressed a coredump — it had not; the coredump happens before the error is
raised, and the only real defect is that the exception could not be pickled.
`copy.deepcopy` hits the same path.
## Changes
**`ffi.Error` now pickles by value.** An error is fully described by its
`(kind, message, backtrace)` strings, so `Error.__reduce__` reconstructs it
through `__init__` rather than the JSON graph. This mirrors `Device` and
`DataType`, which already carry hand-written `__reduce__` implementations for
the same reason.
`extra_context` is intentionally dropped — it may hold arbitrary native
payloads, and preserving it only when it happens to be serializable would make
pickling an error depend on where the error came from.
The attribute stays a live `Error` rather than degrading to `None`, because
`set_last_ffi_error` calls `update_backtrace` on `__tvm_ffi_error__` when a
restored exception propagates back through the FFI; a `None` there would fail
on an unrelated `hasattr` check that is already in the code.
**Clearer errors for the types that genuinely cannot pickle.**
`ffi.Function`, `ffi.Module`, `ffi.Tensor`, and `ffi.OpaquePyObject` each wrap
a live process resource — a code pointer, a `dlopen` handle, a device
allocation, a `PyObject*` — and have no value representation. They are
unchanged behaviorally, but previously surfaced the raw `ToJSONGraph` message,
naming an internal serializer the user never called. That message is now
translated at the `__getstate__` boundary, following CPython's own `cannot
pickle 'X' object` convention:
```
TypeError: cannot pickle `ffi.Function` object: it wraps a callable whose
implementation lives in the current process
```
Nested values name both types, since the failure is not obvious from the
outer object (`arr[0]` returns the plain Python object, so the container looks
picklable):
```
TypeError: cannot pickle `ffi.OpaquePyObject` object contained in `Array`: it
holds an opaque reference to a Python object; pickle the underlying object
directly, or avoid storing non-FFI Python values in containers you intend to
serialize
```
A `TypeError` that is not the unsupported-type error propagates untouched.
## Not in scope
Making `Function`/`Tensor`/`Module`/`OpaquePyObject` serializable.
`OpaquePyObject` in particular should stay unpicklable: the only available
encoding is embedded pickle bytes, which would make the JSON graph non-portable
to C++ consumers, turn `from_json_graph_str` on untrusted input into arbitrary
code execution, and break the identity guarantee (`out is foo`) that is the
whole point of the type.
## Testing
New tests in `tests/python/test_error.py` (exception and bare-`Error` pickle
round trips, `deepcopy`, NULL handle, `extra_context` drop, and re-propagating
a restored exception through an FFI call) and `tests/python/test_object.py`
(message content for each unpicklable type, nested case, and a guard that the
supported types still round-trip).
Full Python suite: 2427 passed, 52 skipped, 2 xfailed. `pre-commit` clean on
all changed files.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]