mirror of
https://github.com/ruby/ruby.git
synced 2026-07-31 09:25:15 +08:00
Use rb_ensure instead of guard objects for Dir.pwd
This replaces GC-based buffer guards (rb_imemo_tmpbuf, TypedData_Wrap_Struct) with rb_ensure to clean up malloc/xmalloc memory when an exception occurs.
This commit is contained in:
parent
06c8b1abfa
commit
126b657bd1
Notes:
git
2026-02-20 01:40:12 +00:00
34
dir.c
34
dir.c
@ -1586,23 +1586,29 @@ dir_chdir(VALUE dir)
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
static VALUE
|
||||
getcwd_to_str(VALUE arg)
|
||||
{
|
||||
const char *path = (const char *)arg;
|
||||
#ifdef __APPLE__
|
||||
return rb_str_normalize_ospath(path, strlen(path));
|
||||
#else
|
||||
return rb_str_new2(path);
|
||||
#endif
|
||||
}
|
||||
|
||||
static VALUE
|
||||
getcwd_xfree(VALUE arg)
|
||||
{
|
||||
xfree((void *)arg);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_dir_getwd_ospath(void)
|
||||
{
|
||||
char *path;
|
||||
VALUE cwd;
|
||||
VALUE path_guard;
|
||||
|
||||
path_guard = rb_imemo_tmpbuf_new();
|
||||
path = ruby_getcwd();
|
||||
rb_imemo_tmpbuf_set_ptr(path_guard, path);
|
||||
#ifdef __APPLE__
|
||||
cwd = rb_str_normalize_ospath(path, strlen(path));
|
||||
#else
|
||||
cwd = rb_str_new2(path);
|
||||
#endif
|
||||
rb_free_tmp_buffer(&path_guard);
|
||||
return cwd;
|
||||
char *path = ruby_getcwd();
|
||||
return rb_ensure(getcwd_to_str, (VALUE)path, getcwd_xfree, (VALUE)path);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
36
util.c
36
util.c
@ -529,45 +529,43 @@ ruby_strdup(const char *str)
|
||||
char *
|
||||
ruby_getcwd(void)
|
||||
{
|
||||
VALUE guard = rb_imemo_tmpbuf_new();
|
||||
int size = 200;
|
||||
char *buf = xmalloc(size);
|
||||
|
||||
while (!getcwd(buf, size)) {
|
||||
int e = errno;
|
||||
if (e != ERANGE) {
|
||||
rb_free_tmp_buffer(&guard);
|
||||
xfree(buf);
|
||||
rb_syserr_fail(e, "getcwd");
|
||||
}
|
||||
size *= 2;
|
||||
rb_imemo_tmpbuf_set_ptr(guard, buf);
|
||||
buf = xrealloc(buf, size);
|
||||
xfree(buf);
|
||||
buf = xmalloc(size);
|
||||
}
|
||||
rb_imemo_tmpbuf_set_ptr(guard, NULL);
|
||||
return buf;
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
static const rb_data_type_t getcwd_buffer_guard_type = {
|
||||
.wrap_struct_name = "ruby_getcwd_guard",
|
||||
.function = {
|
||||
.dfree = free // not xfree.
|
||||
},
|
||||
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
|
||||
};
|
||||
static VALUE
|
||||
getcwd_strdup(VALUE arg)
|
||||
{
|
||||
return (VALUE)ruby_strdup((const char *)arg);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
getcwd_free(VALUE arg)
|
||||
{
|
||||
free((void *)arg);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
char *
|
||||
ruby_getcwd(void)
|
||||
{
|
||||
VALUE guard = TypedData_Wrap_Struct((VALUE)0, &getcwd_buffer_guard_type, NULL);
|
||||
char *buf, *cwd = getcwd(NULL, 0);
|
||||
RTYPEDDATA_DATA(guard) = cwd;
|
||||
char *cwd = getcwd(NULL, 0);
|
||||
if (!cwd) rb_sys_fail("getcwd");
|
||||
buf = ruby_strdup(cwd); /* allocate by xmalloc */
|
||||
free(cwd);
|
||||
RTYPEDDATA_DATA(RB_GC_GUARD(guard)) = NULL;
|
||||
return buf;
|
||||
return (char *)rb_ensure(getcwd_strdup, (VALUE)cwd, getcwd_free, (VALUE)cwd);
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user