Skip to content

Delete copy/move on IceRuby classes that register a GC root#5674

Merged
pepone merged 2 commits into
mainfrom
fix/iceruby-delete-copy-move
Jun 23, 2026
Merged

Delete copy/move on IceRuby classes that register a GC root#5674
pepone merged 2 commits into
mainfrom
fix/iceruby-delete-copy-move

Conversation

@pepone

@pepone pepone commented Jun 23, 2026

Copy link
Copy Markdown
Member

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 rb_gc_unregister_address an address that was never registered. All four special members are now explicitly = 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.

This is not an active bug today (these are only ever created with make_shared and handled through a shared_ptr), so it's hardening only with no behavior change — a good fit for 3.9.0.

Closes #5591

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
Copilot AI review requested due to automatic review settings June 23, 2026 09:03
@pepone pepone added the ruby label Jun 23, 2026
@pepone pepone requested a review from bernardnormier June 23, 2026 09:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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::ValueWriter and IceRuby::ValueReader.
  • Deleted copy/move constructors and assignment operators for IceRuby::RubySliceLoader.
  • Kept IceRuby::ExceptionReader copyable (required by throw *this / make_exception_ptr semantics) 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.

Comment thread ruby/src/IceRuby/Types.h Outdated
Comment on lines +511 to +516
// 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;
Comment thread ruby/src/IceRuby/Types.h
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&);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have a copy constructor and a destructor, no need to delete the move constructor. I would undo this update to ExceptionReader.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 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.
@pepone pepone merged commit 3f6d563 into main Jun 23, 2026
55 of 56 checks passed
@pepone pepone deleted the fix/iceruby-delete-copy-move branch June 24, 2026 12:08
pepone added a commit that referenced this pull request Jul 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Delete copy/move on IceRuby VALUE-wrapper classes that register a GC root

3 participants