Serializing a program with CUDA parameters segfaults the emitter
to_executorch() crashes with a segmentation fault when a program's constant
tensors live in device memory. The emitter reads a constant's storage through a
host pointer cast, with no check of where that storage actually is:
# exir/emit/_emitter.py, _tensor_spec_to_evalue
buffer_data = bytes(
ctypes.cast(
typing.cast(torch.UntypedStorage, spec.storage).data_ptr(),
ctypes.POINTER(spec_array_type),
).contents
)
data_ptr() on a CUDA storage is a device address, so ctypes.cast reads device
memory from the host.
Reproducer, on a machine with a CUDA build of torch:
import torch
from torch.export import export
from executorch.exir import to_edge_transform_and_lower
model = torch.nn.Sequential(torch.nn.Linear(4, 3), torch.nn.ReLU()).eval().cuda()
example = torch.ones(2, 4).cuda()
program = to_edge_transform_and_lower(export(model, (example,))).to_executorch()
The faulthandler traceback points straight at the cast:
Fatal Python error: Segmentation fault
Current thread ...:
File ".../executorch/exir/emit/_emitter.py", line 460 in _tensor_spec_to_evalue
The same script with host parameters succeeds, which is the workaround: keep
parameters on the host and let the partitioner see the device only through the
example input.
Suggested fix: copy the storage to the host before serializing when it is not
already there, or fail with a clear message instead of reading device memory
from the host.
Found while running an end-to-end delegate export on Linux aarch64. Not specific
to any one backend, since the crash is in the shared serialization path.
Serializing a program with CUDA parameters segfaults the emitter
to_executorch()crashes with a segmentation fault when a program's constanttensors live in device memory. The emitter reads a constant's storage through a
host pointer cast, with no check of where that storage actually is:
data_ptr()on a CUDA storage is a device address, soctypes.castreads devicememory from the host.
Reproducer, on a machine with a CUDA build of torch:
The faulthandler traceback points straight at the cast:
The same script with host parameters succeeds, which is the workaround: keep
parameters on the host and let the partitioner see the device only through the
example input.
Suggested fix: copy the storage to the host before serializing when it is not
already there, or fail with a clear message instead of reading device memory
from the host.
Found while running an end-to-end delegate export on Linux aarch64. Not specific
to any one backend, since the crash is in the shared serialization path.