Box: remove copied extension files

This commit is contained in:
Nobuyoshi Nakada 2025-11-08 11:05:17 +09:00 committed by Nobuyoshi Nakada
parent e8568bbcf2
commit 573896a40a
Notes: git 2025-12-09 14:42:24 +00:00
4 changed files with 74 additions and 19 deletions

60
box.c
View File

@ -62,6 +62,7 @@ bool ruby_box_crashed = false; // extern, changed only in vm.c
VALUE rb_resolve_feature_path(VALUE klass, VALUE fname);
static VALUE rb_box_inspect(VALUE obj);
static void cleanup_all_local_extensions(VALUE libmap);
void
rb_box_init_done(void)
@ -274,6 +275,8 @@ box_entry_free(void *ptr)
st_foreach(box->classext_cow_classes, free_classext_for_box, (st_data_t)box);
}
cleanup_all_local_extensions(box->ruby_dln_libmap);
box_root_free(ptr);
xfree(ptr);
}
@ -724,8 +727,57 @@ escaped_basename(const char *path, const char *fname, char *rvalue, size_t rsize
}
}
static void
box_ext_cleanup_mark(void *p)
{
rb_gc_mark((VALUE)p);
}
static void
box_ext_cleanup_free(void *p)
{
VALUE path = (VALUE)p;
unlink(RSTRING_PTR(path));
}
static const rb_data_type_t box_ext_cleanup_type = {
"box_ext_cleanup",
{box_ext_cleanup_mark, box_ext_cleanup_free},
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
};
void
rb_box_cleanup_local_extension(VALUE cleanup)
{
void *p = DATA_PTR(cleanup);
DATA_PTR(cleanup) = NULL;
#ifndef _WIN32
if (p) box_ext_cleanup_free(p);
#endif
}
static int
cleanup_local_extension_i(VALUE key, VALUE value, VALUE arg)
{
#if defined(_WIN32)
HMODULE h = (HMODULE)NUM2SVALUE(value);
WCHAR module_path[MAXPATHLEN];
DWORD len = GetModuleFileNameW(h, module_path, numberof(module_path));
FreeLibrary(h);
if (len > 0 && len < numberof(module_path)) DeleteFileW(module_path);
#endif
return ST_DELETE;
}
static void
cleanup_all_local_extensions(VALUE libmap)
{
rb_hash_foreach(libmap, cleanup_local_extension_i, 0);
}
VALUE
rb_box_local_extension(VALUE box_value, VALUE fname, VALUE path)
rb_box_local_extension(VALUE box_value, VALUE fname, VALUE path, VALUE *cleanup)
{
char ext_path[MAXPATHLEN], fname2[MAXPATHLEN], basename[MAXPATHLEN];
int wrote;
@ -739,14 +791,16 @@ rb_box_local_extension(VALUE box_value, VALUE fname, VALUE path)
if (wrote >= (int)sizeof(ext_path)) {
rb_bug("Extension file path in the box was too long");
}
VALUE new_path = rb_str_new_cstr(ext_path);
*cleanup = TypedData_Wrap_Struct(0, &box_ext_cleanup_type, NULL);
enum copy_error_type copy_error = copy_ext_file(src_path, ext_path);
if (copy_error) {
char message[1024];
copy_ext_file_error(message, sizeof(message), copy_error);
rb_raise(rb_eLoadError, "can't prepare the extension file for Ruby Box (%s from %"PRIsVALUE"): %s", ext_path, path, message);
}
// TODO: register the path to be clean-uped
return rb_str_new_cstr(ext_path);
DATA_PTR(*cleanup) = (void *)new_path;
return new_path;
}
// TODO: delete it just after dln_load? or delay it?

View File

@ -3,6 +3,16 @@
#include "ruby/ruby.h" /* for VALUE */
#if SIZEOF_VALUE <= SIZEOF_LONG
# define SVALUE2NUM(x) LONG2NUM((long)(x))
# define NUM2SVALUE(x) (SIGNED_VALUE)NUM2LONG(x)
#elif SIZEOF_VALUE <= SIZEOF_LONG_LONG
# define SVALUE2NUM(x) LL2NUM((LONG_LONG)(x))
# define NUM2SVALUE(x) (SIGNED_VALUE)NUM2LL(x)
#else
# error Need integer for VALUE
#endif
/**
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
@ -75,7 +85,8 @@ void rb_box_gc_update_references(void *ptr);
rb_box_t * rb_get_box_t(VALUE ns);
VALUE rb_get_box_object(rb_box_t *ns);
VALUE rb_box_local_extension(VALUE box, VALUE fname, VALUE path);
VALUE rb_box_local_extension(VALUE box, VALUE fname, VALUE path, VALUE *cleanup);
void rb_box_cleanup_local_extension(VALUE cleanup);
void rb_initialize_main_box(void);
void rb_box_init_done(void);

16
load.c
View File

@ -27,16 +27,6 @@
#define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0)
#define IS_DLEXT(e) (strcmp((e), DLEXT) == 0)
#if SIZEOF_VALUE <= SIZEOF_LONG
# define SVALUE2NUM(x) LONG2NUM((long)(x))
# define NUM2SVALUE(x) (SIGNED_VALUE)NUM2LONG(x)
#elif SIZEOF_VALUE <= SIZEOF_LONG_LONG
# define SVALUE2NUM(x) LL2NUM((LONG_LONG)(x))
# define NUM2SVALUE(x) (SIGNED_VALUE)NUM2LL(x)
#else
# error Need integer for VALUE
#endif
enum {
loadable_ext_rb = (0+ /* .rb extension is the first in both tables */
1) /* offset by rb_find_file_ext() */
@ -1203,11 +1193,15 @@ load_ext(VALUE path, VALUE fname)
{
VALUE loaded = path;
const rb_box_t *box = rb_loading_box();
VALUE cleanup = 0;
if (BOX_USER_P(box)) {
loaded = rb_box_local_extension(box->box_object, fname, path);
loaded = rb_box_local_extension(box->box_object, fname, path, &cleanup);
}
rb_scope_visibility_set(METHOD_VISI_PUBLIC);
void *handle = dln_load_feature(RSTRING_PTR(loaded), RSTRING_PTR(fname));
if (cleanup) {
rb_box_cleanup_local_extension(cleanup);
}
RB_GC_GUARD(loaded);
RB_GC_GUARD(fname);
return (VALUE)handle;

View File

@ -697,10 +697,6 @@ class TestBox < Test::Unit::TestCase
assert !$LOADED_FEATURES.include?("/tmp/barbaz")
assert !Object.const_defined?(:FooClass)
end;
ensure
tmp = ENV["TMPDIR"] || ENV["TMP"] || Etc.systmpdir || "/tmp"
pat = "_ruby_ns_*."+RbConfig::CONFIG["DLEXT"]
File.unlink(*Dir.glob(pat, base: tmp).map {|so| "#{tmp}/#{so}"})
end
def test_basic_box_detections