[#3419] Valgrind analysis of [BUG] unknown node type 0 — Andrew Walrond <andrew@...>

Hello list,

19 messages 2004/09/17
[#3422] Re: Valgrind analysis of [BUG] unknown node type 0 — ts <decoux@...> 2004/09/17

>>>>> "A" == Andrew Walrond <andrew@walrond.org> writes:

[#3423] Re: Valgrind analysis of [BUG] unknown node type 0 — Andrew Walrond <andrew@...> 2004/09/17

On Friday 17 Sep 2004 12:01, ts wrote:

[#3424] Re: Valgrind analysis of [BUG] unknown node type 0 — ts <decoux@...> 2004/09/17

>>>>> "A" == Andrew Walrond <andrew@walrond.org> writes:

[#3425] Re: Valgrind analysis of [BUG] unknown node type 0 — Andrew Walrond <andrew@...> 2004/09/17

On Friday 17 Sep 2004 12:37, ts wrote:

[#3426] Re: Valgrind analysis of [BUG] unknown node type 0 — ts <decoux@...> 2004/09/17

>>>>> "A" == Andrew Walrond <andrew@walrond.org> writes:

[#3428] Re: Valgrind analysis of [BUG] unknown node type 0 — Andrew Walrond <andrew@...> 2004/09/17

On Friday 17 Sep 2004 13:05, ts wrote:

[#3429] Re: Valgrind analysis of [BUG] unknown node type 0 — ts <decoux@...> 2004/09/17

>>>>> "A" == Andrew Walrond <andrew@walrond.org> writes:

[PATCH] dir.c (II)

From: Johan Holmberg <holmberg@...>
Date: 2004-09-17 22:19:18 UTC
List: ruby-core #3446
It has been interesting to follow the discussion following my
original patch proposal (but I can't say I understood everything).

I noticed today that dir.c was updated in the CVS archives to fix
the problem I described in my original mail. But after looking at
the change, I think it can be improved in some ways:

1) the "dir_chdir" call in "chdir_restore" is done
   even if the first call failed. I don't think this is
   "logically correct" to do: one shouldn't undo something that was
   never done. See the end of the mail for a weird example (taken
   from a testcase I added to the Rubytests on Rubyforge).

2) the memory leak that was mentioned in the previous thread doesn't
   seem to have been fixed in the change commited today.

Below is a new patch that I think solves these issues. I have also
reorganized the code somewhat, so that "chdir_yield" and
"chdir_restore" are more symmetric, and renamed some variables so
the code becomes easier to read (hopefully).

I hope the change can be useful.

/Johan Holmberg

Below follows:

     - the patch
     - a testcase fragment to demonstrate 1) above

Index: dir.c
===================================================================
RCS file: /src/ruby/dir.c,v
retrieving revision 1.126
diff -u -r1.126 dir.c
--- dir.c	17 Sep 2004 09:24:13 -0000	1.126
+++ dir.c	17 Sep 2004 21:34:44 -0000
@@ -687,26 +687,38 @@
 static VALUE chdir_thread = Qnil;

 struct chdir_data {
-    char *dist;
-    VALUE path;
+    char *old_cwd;
+    char *new_cwd;
+    VALUE yield_arg;
+    int chdir_done;
 };

 static VALUE
 chdir_yield(args)
     struct chdir_data *args;
 {
-    dir_chdir(args->dist);
-    return rb_yield(args->path);
+    dir_chdir(args->new_cwd);
+    args->chdir_done = 1;
+
+    chdir_blocking++;
+    if (chdir_thread == Qnil)
+	chdir_thread = rb_thread_current();
+
+    return rb_yield(args->yield_arg);
 }

 static VALUE
-chdir_restore(path)
-    char *path;
+chdir_restore(args)
+    struct chdir_data *args;
 {
-    chdir_blocking--;
-    if (chdir_blocking == 0)
-	chdir_thread = Qnil;
-    dir_chdir(path);
+    if (args->chdir_done) {
+	chdir_blocking--;
+	if (chdir_blocking == 0)
+	    chdir_thread = Qnil;
+
+	dir_chdir(args->old_cwd);
+    }
+    free(args->old_cwd);
     return Qnil;
 }

@@ -777,15 +789,13 @@
     }

     if (rb_block_given_p()) {
-	char *cwd = my_getcwd();
 	struct chdir_data args;
+	args.old_cwd    = my_getcwd();
+	args.new_cwd    = dist;
+	args.yield_arg  = path;
+	args.chdir_done = 0;

-	chdir_blocking++;
-	if (chdir_thread == Qnil)
-	    chdir_thread = rb_thread_current();
-	args.dist = dist;
-	args.path = path;
-	return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)cwd);
+	return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
     }
     dir_chdir(dist);

---------------------------------------------------------------------------
---------------------------------------------------------------------------

    # chdir with block to non-existing dir, and a directory above that
    # is unaccessible => we should still get Errno::ENOENT.
    Dir.chdir("_test") do
      Dir.mkdir("inaccessible")
      Dir.mkdir("inaccessible/subdir")
      Dir.chdir("inaccessible/subdir") do
        old_mode = File.stat("..").mode
        begin
          File.chmod(0, "..")  # make "inaccessible" live up to its name
          assert_raises(Errno::ENOENT) do
            Dir.chdir("non-existing") do
              # never reached
            end
          end
        ensure
          File.chmod(old_mode, "..")  # restore "inaccessible"
        end
      end
    end

---------------------------------------------------------------------------
---------------------------------------------------------------------------


In This Thread

Prev Next