danielpclark/rutie

Implement bindings to ruby_sysinit and ruby_init_stack (Segmentation fault in Windows on VM#init)

somedevfox opened this issue · 0 comments

Hello all,

Description of issue

Rutie is missing bindings to Virtual Machine Initialization methods such as ruby_sysinit and ruby_init_stack which are vital on Windows New Technology Operating Systems.
If one does not use them, they will get STATUS_ACCESS_VIOLATION (Segmentation Fault) on Ruby 3.1 (and on previous versions, perhaps?).

Host information

OS Version: Windows 10 21H2 (19044.1889)
Rust Version: 1.65.0-nightly
Linked with Ruby Version: 3.1

Steps to reproduce STATUS_ACCESS_VIOLATION

  1. Install dependencies
  1. Clone rcxp
  2. Run in shell cargo run
  3. error: process didn't exit successfully: 'target\debug\rcxp.exe' (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)

Method signatures and their descriptions:

// ruby/interpreter.h


/**
 * Initializes the process for libruby.
 *
 * This function assumes this process is `ruby(1)` and it has just started.
 * Usually programs that embed CRuby interpreter may not call this function,
 * and may do their own initialization.
 *
 * @param[in]  argc  Pointer to process main's `argc`.
 * @param[in]  argv  Pointer to process main's `argv`.
 * @warning    `argc` and `argv` cannot be `NULL`.
 *
 * @internal
 *
 * AFAIK Ruby does write to argv, especially `argv[0][0]`, via setproctitle(3).
 * It is intentional that the argument is not const-qualified.
 */
void ruby_sysinit(int *argc, char ***argv);

/**
 * Set stack bottom of Ruby implementation.
 *
 * You  must   call  this   function  before  any   heap  allocation   by  Ruby
 * implementation.  Or GC will break living objects.
 *
 * @param[in]  addr  A pointer somewhere on the stack, near its bottom.
 */
void ruby_init_stack(volatile VALUE *addr);

And I'm pretty sure they're needed, since I also tried initializing Ruby Virtual Machine from Pure C and it didn't work without at least ruby_sysinit.

So, there are two options.

  1. Implement VM#init_sys - ruby_sysinit and VM#init_stack - ruby_init_stack, requiring Rutie Dev to use them before VM Initialization.
  2. Instead of implementing two new methods, we can modfy VM#init to use these functions internally, freeing the developer from additional code.

What's the better way to go around this?