diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-09-18 06:56:38 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-09-18 06:56:38 +0000 |
commit | de5a85496ac4ae7bd24b5fc7acb8001a5e4d8b7d (patch) | |
tree | 0ad108b04b1012522217a02b8e7f7dd940943759 /dir.c | |
parent | 4c28c7d1af7ce6c30cc1bc9c0e5685c0ef17dc13 (diff) |
* array.c (rb_ary_equal): element size might change during
comparison. [ruby-dev:24254]
* array.c (rb_ary_diff): ditto. [ruby-dev:24274]
* array.c (rb_ary_select): ditto. [ruby-dev:24278]
* array.c (rb_ary_delete): ditto. [ruby-dev:24283]
* array.c (rb_ary_rindex): ditto. [ruby-dev:24275]
* array.c (rb_ary_initialize): element size might change during
initializing block. [ruby-dev:24284]
* dir.c (dir_s_chdir): avoid memory leak and unnecessary chdir to
the original directory when exception has caused in changing
direcotry or within block. thanks to Johan Holmberg
<holmberg@iar.se> [ruby-core:03446]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@6922 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'dir.c')
-rw-r--r-- | dir.c | 57 |
1 files changed, 37 insertions, 20 deletions
@@ -542,24 +542,42 @@ dir_close(dir) static void dir_chdir(path) - const char *path; + VALUE path; { - if (chdir(path) < 0) - rb_sys_fail(path); + if (chdir(RSTRING(path)->ptr) < 0) + rb_sys_fail(RSTRING(path)->ptr); } static int chdir_blocking = 0; static VALUE chdir_thread = Qnil; +struct chdir_data { + VALUE old_path, new_path; + int done; +}; + static VALUE -chdir_restore(path) - char *path; +chdir_yield(args) + struct chdir_data *args; { - chdir_blocking--; - if (chdir_blocking == 0) - chdir_thread = Qnil; - dir_chdir(path); - free(path); + dir_chdir(args->new_path); + args->done = Qtrue; + chdir_blocking++; + if (chdir_thread == Qnil) + chdir_thread = rb_thread_current(); + return rb_yield(args->new_path); +} + +static VALUE +chdir_restore(args) + struct chdir_data *args; +{ + if (args->done) { + chdir_blocking--; + if (chdir_blocking == 0) + chdir_thread = Qnil; + dir_chdir(args->old_path); + } return Qnil; } @@ -609,19 +627,18 @@ dir_s_chdir(argc, argv, obj) VALUE obj; { VALUE path = Qnil; - char *dist = ""; rb_secure(2); if (rb_scan_args(argc, argv, "01", &path) == 1) { SafeStringValue(path); - dist = RSTRING(path)->ptr; } else { - dist = getenv("HOME"); + const char *dist = getenv("HOME"); if (!dist) { dist = getenv("LOGDIR"); if (!dist) rb_raise(rb_eArgError, "HOME/LOGDIR not set"); } + path = rb_str_new2(dist); } if (chdir_blocking > 0) { @@ -630,14 +647,14 @@ dir_s_chdir(argc, argv, obj) } if (rb_block_given_p()) { - char *cwd = my_getcwd(); - chdir_blocking++; - if (chdir_thread == Qnil) - chdir_thread = rb_thread_current(); - dir_chdir(dist); - return rb_ensure(rb_yield, path, chdir_restore, (VALUE)cwd); + struct chdir_data args; + + args.old_path = rb_str_new2(my_getcwd()); + args.new_path = path; + args.done = Qfalse; + return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args); } - dir_chdir(dist); + dir_chdir(path); return INT2FIX(0); } |