[ruby-core:117220] [Ruby master Feature#19057] Hide implementation of `rb_io_t`.

Issue #19057 has been updated by mame (Yusuke Endoh). Why don't you reconsider the "nested public interface" approach? From the reaction to this ticket, it is clear that forcing the "hide all the details" approach could destroy the Ruby ecosystem. And there is no need to force it because you have a more moderate alternative approach. ---------------------------------------- Feature #19057: Hide implementation of `rb_io_t`. https://bugs.ruby-lang.org/issues/19057#change-107306 * Author: ioquatix (Samuel Williams) * Status: Assigned * Assignee: ioquatix (Samuel Williams) * Target version: 3.4 ---------------------------------------- In order to make improvements to the IO implementation like <https://bugs.ruby-lang.org/issues/18455>, we need to add new fields to `struct rb_io_t`. By the way, ending types in `_t` is not recommended by POSIX, so I'm also trying to rename the internal implementation to drop `_t` where possible during this conversion. Anyway, we should try to hide the implementation of `struct rb_io`. Ideally, we don't expose any of it, but the problem is backwards compatibility. So, in order to remain backwards compatibility, we should expose some fields of `struct rb_io`, the most commonly used one is `fd` and `mode`, but several others are commonly used. There are many fields which should not be exposed because they are implementation details. ## Current proposal The current proposed change <https://github.com/ruby/ruby/pull/6511> creates two structs: ```c // include/ruby/io.h #ifndef RB_IO_T struct rb_io { int fd; // ... public fields ... }; #else struct rb_io; #endif // internal/io.h #define RB_IO_T struct rb_io { int fd; // ... public fields ... // ... private fields ... }; ``` However, we are not 100% confident this is safe according to the C specification. My experience is not sufficiently wide to say this is safe in practice, but it does look okay to both myself, and @Eregon + @tenderlovemaking have both given some kind of approval. That being said, maybe it's not safe. There are two alternatives: ## Hide all details We can make public `struct rb_io` completely invisible. ```c // include/ruby/io.h #define RB_IO_HIDDEN struct rb_io; int rb_ioptr_descriptor(struct rb_io *ioptr); // accessor for previously visible state. // internal/io.h struct rb_io { // ... all fields ... }; ``` This would only be forwards compatible, and code would need to feature detect like this: ```c #ifdef RB_IO_HIDDEN #define RB_IOPTR_DESCRIPTOR rb_ioptr_descriptor #else #define RB_IOPTR_DESCRIPTOR(ioptr) rb_ioptr_descriptor(ioptr) #endif ``` ## Nested public interface Alternatively, we can nest the public fields into the private struct: ```c // include/ruby/io.h struct rb_io_public { int fd; // ... public fields ... }; // internal/io.h #define RB_IO_T struct rb_io { struct rb_io_public public; // ... private fields ... }; ``` ## Considerations I personally think the "Hide all details" implementation is the best, but it's also the lest compatible. This is also what we are ultimately aiming for, whether we decide to take an intermediate "compatibility step" is up to us. I think "Nested public interface" is messy and introduces more complexity, but it might be slightly better defined than the "Current proposal" which might create undefined behaviour. That being said, all the tests are passing. -- https://bugs.ruby-lang.org/

ioquatix (Samuel Williams) wrote:
- Companies could contact Eric and offer incentives for him to make a release.
That's not possible, https://yhbt.net/unicorn/ISSUES states: The author of unicorn must never be allowed to profit off the damage it's done to the entire Ruby world. I'm 100% banned for life from ever profitting off anything related to unicorn. "mame (Yusuke Endoh) via ruby-core" <ruby-core@ml.ruby-lang.org> wrote:
Why don't you reconsider the "nested public interface" approach?
Samuel: please do this. Ruby even has (Linux||ccan) `container_of' macro as another option: struct rb_io_private { struct rb_io { // public ABI int fd; // any other public fields in used in real-world } io_pub; // private stuff here // private fields can go above `io_pub', too }; Then only expose the `io_pub' field to public structs and access rb_io_private via ccan_container_of. But the previously discussed ways are valid C since every known platform has a stable ABI (otherwise FFI would never work) I expect there are other gems and private extensions affected by this C API change (if they survived the 1.8 -> 1.9 changes).
From the reaction to this ticket, it is clear that forcing the "hide all the details" approach could destroy the Ruby ecosystem. And there is no need to force it because you have a more moderate alternative approach.
Too bad that's already happened over the decades I've been around Ruby. Ruby lost numerous users due to a neverending stream of incompatibilities introduced every year. The only way I can maintain the legacy Ruby code I still have is to rewrite tests in a different language (e.g. Perl or POSIX sh (NOT bash)) I'm completely burned out with having to constantly deal with a never ending stream of incompatibilities over the past ~20 years. This mentality has propagated to the entire ecosystem; e.g. Rack::Chunked was deprecated and my proposed patches sent to rack-devel@googlegroups.com to maintain compatibility were completely ignored in Sep 2022. frozen_string_literal will be another major pain point, and the nagging from chilled strings won't do much to make things better (I thought that was decided against a decade ago). Finally, MFA on Rubygems is a misguided corporate attempt at security. I'm an amateur volunteer refuse to be held responsible for the security of multi-billion dollar corporations. I've never claimed any professional or academic qualifications. Nobody knows me, nobody ever will; I only show you code and that's all anybody should need for security. I'll probably end up self-hosting my own gems and only put future releases on a self-hosted server. Of course, I claim no qualifications in security or systems administration. Users are welcome to fork (and pitchfork exists) if they'd rather live under the boot of corporate rule and Terms of Service that can change at any time. I'm not going to put myself in a position where I can't contribute to code I still depend on. I'm already effectively banned from 99.9% of projects due to draconian corporate terms of service and high HW requirements.
participants (2)
-
Eric Wong
-
mame (Yusuke Endoh)