Delete copy/move on IceRuby classes that register a GC root#5674
Conversation
RubySliceLoader, ValueWriter and ValueReader register a Ruby GC root tied to the address of a VALUE member (rb_gc_register_address(&_member)), so they are logically non-copyable and non-movable: a default copy/move would not re-register the new instance's address, and the moved-from/copied instance's destructor would unregister an address that was never registered. Mark all four special members deleted. ExceptionReader must stay copyable -- ice_throw does `throw *this` and make_exception_ptr copies it -- and its copy constructor already re-registers a fresh root, so only its move constructor and assignment operators are deleted. Hardening only, no behavior change. Closes #5591
There was a problem hiding this comment.
Pull request overview
This PR hardens the IceRuby C++ wrappers around Ruby VALUE handles by explicitly deleting copy/move special members for types that register Ruby GC roots by address (rb_gc_register_address(&member)), preventing accidental object copies/moves that would invalidate GC root registration.
Changes:
- Deleted copy/move constructors and assignment operators for
IceRuby::ValueWriterandIceRuby::ValueReader. - Deleted copy/move constructors and assignment operators for
IceRuby::RubySliceLoader. - Kept
IceRuby::ExceptionReadercopyable (required bythrow *this/make_exception_ptrsemantics) while deleting its move ctor and assignment operators.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| ruby/src/IceRuby/Types.h | Deletes copy/move/assign special members for ValueWriter, ValueReader, and partially for ExceptionReader to match GC-root-by-address semantics. |
| ruby/src/IceRuby/RubySliceLoader.h | Deletes copy/move/assign special members for RubySliceLoader to match GC-root-by-address semantics. |
| // Copyable (ice_throw throws *this, and make_exception_ptr copies); the copy constructor re-registers a fresh | ||
| // GC root for _ex. Registering a root tied to the address of _ex makes it non-movable and non-assignable. | ||
| ExceptionReader(const ExceptionReader&); | ||
| ExceptionReader(ExceptionReader&&) = delete; | ||
| ExceptionReader& operator=(const ExceptionReader&) = delete; | ||
| ExceptionReader& operator=(ExceptionReader&&) = delete; |
| ExceptionReader(const ExceptionInfoPtr&); | ||
| // Copyable (ice_throw throws *this, and make_exception_ptr copies); the copy constructor re-registers a fresh | ||
| // GC root for _ex. Registering a root tied to the address of _ex makes it non-movable and non-assignable. | ||
| ExceptionReader(const ExceptionReader&); |
There was a problem hiding this comment.
We already have a copy constructor and a destructor, no need to delete the move constructor. I would undo this update to ExceptionReader.
There was a problem hiding this comment.
🤖 Claude: Done in 7cea509 — reverted the ExceptionReader update. The copy constructor + destructor already suppress the implicit move constructor, so the deletes were redundant.
ExceptionReader's user-declared copy constructor and destructor already suppress the implicit move constructor, so deleting the move constructor and the assignment operators was redundant.
(cherry picked from commit 3f6d563)
RubySliceLoader,ValueWriterandValueReaderregister a Ruby GC root tied to the address of aVALUEmember (rb_gc_register_address(&_member)), so they are logically non-copyable and non-movable: a default copy/move would not re-register the new instance's address, and the moved-from/copied instance's destructor wouldrb_gc_unregister_addressan address that was never registered. All four special members are now explicitly= deleted.ExceptionReadermust stay copyable —ice_throwdoesthrow *thisandmake_exception_ptrcopies it — and its copy constructor already re-registers a fresh root, so only its move constructor and assignment operators are deleted.This is not an active bug today (these are only ever created with
make_sharedand handled through ashared_ptr), so it's hardening only with no behavior change — a good fit for 3.9.0.Closes #5591