[前][次][番号順一覧][スレッド一覧]

ruby-changes:51066

From: nobu <ko1@a...>
Date: Fri, 27 Apr 2018 16:39:06 +0900 (JST)
Subject: [ruby-changes:51066] nobu:r63273 (trunk): mjit.c: clean so file on Windows

nobu	2018-04-27 16:39:00 +0900 (Fri, 27 Apr 2018)

  New Revision: 63273

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=63273

  Log:
    mjit.c: clean so file on Windows
    
    * mjit.c (dlclose): use FreeLibrary to manage the reference count
      on the loaded module properly.
    
    * mjit.c (clean_so_file): clean shared object file after unloaded,
      in-use files cannot be removed on Windows.

  Modified files:
    trunk/mjit.c
    trunk/test/lib/jit_support.rb
    trunk/test/ruby/test_jit.rb
Index: mjit.c
===================================================================
--- mjit.c	(revision 63272)
+++ mjit.c	(revision 63273)
@@ -115,7 +115,7 @@ extern int rb_thread_create_mjit_thread( https://github.com/ruby/ruby/blob/trunk/mjit.c#L115
 #define dlopen(name,flag) ((void*)LoadLibrary(name))
 #define dlerror() strerror(rb_w32_map_errno(GetLastError()))
 #define dlsym(handle,name) ((void*)GetProcAddress((handle),(name)))
-#define dlclose(handle) (CloseHandle(handle))
+#define dlclose(handle) (FreeLibrary(handle))
 #define RTLD_NOW  -1
 
 #define waitpid(pid,stat_loc,options) (WaitForSingleObject((HANDLE)(pid), INFINITE), GetExitCodeProcess((HANDLE)(pid), (LPDWORD)(stat_loc)))
@@ -148,6 +148,10 @@ struct rb_mjit_unit { https://github.com/ruby/ruby/blob/trunk/mjit.c#L148
     /* Dlopen handle of the loaded object file.  */
     void *handle;
     const rb_iseq_t *iseq;
+#ifdef _WIN32
+    /* DLL cannot be removed while loaded on Windows */
+    char *so_file;
+#endif
     /* Only used by unload_units. Flag to check this unit is currently on stack or not. */
     char used_code_p;
 };
@@ -442,12 +446,30 @@ mjit_free_iseq(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/mjit.c#L446
 }
 
 static void
+clean_so_file(struct rb_mjit_unit *unit)
+{
+#ifdef _WIN32
+# undef Sleep
+    char *so_file = unit->so_file;
+    if (so_file) {
+        unit->so_file = NULL;
+        if (remove(so_file)) {
+            fprintf(stderr, "failed to remove \"%s\": %s\n",
+                    so_file, strerror(errno));
+        }
+        free(so_file);
+    }
+#endif
+}
+
+static void
 free_unit(struct rb_mjit_unit *unit)
 {
     if (unit->iseq) /* ISeq is not GCed */
         unit->iseq->body->jit_func = 0;
     if (unit->handle) /* handle is NULL if it's in queue */
         dlclose(unit->handle);
+    clean_so_file(unit);
     xfree(unit);
 }
 
@@ -865,8 +887,13 @@ convert_unit_to_func(struct rb_mjit_unit https://github.com/ruby/ruby/blob/trunk/mjit.c#L887
     }
 
     func = load_func_from_so(so_file, funcname, unit);
-    if (!mjit_opts.save_temps)
+    if (!mjit_opts.save_temps) {
+#ifdef _WIN32
+        unit->so_file = strdup(so_file);
+#else
         remove(so_file);
+#endif
+    }
 
     if ((ptrdiff_t)func > (ptrdiff_t)LAST_JIT_ISEQ_FUNC) {
         struct rb_mjit_unit_node *node = create_list_node(unit);
@@ -1095,6 +1122,7 @@ unload_units(void) https://github.com/ruby/ruby/blob/trunk/mjit.c#L1122
         assert(unit->handle != NULL);
         dlclose(unit->handle);
         unit->handle = NULL;
+        clean_so_file(unit);
     }
     verbose(1, "Too many JIT code -- %d units unloaded", units_num - active_units.length);
 }
Index: test/lib/jit_support.rb
===================================================================
--- test/lib/jit_support.rb	(revision 63272)
+++ test/lib/jit_support.rb	(revision 63273)
@@ -7,9 +7,12 @@ module JITSupport https://github.com/ruby/ruby/blob/trunk/test/lib/jit_support.rb#L7
   ]
 
   module_function
-  def eval_with_jit(script, verbose: 0, min_calls: 5, timeout: JIT_TIMEOUT)
-    EnvUtil.invoke_ruby(
-      ['--disable-gems', '--jit-wait', "--jit-verbose=#{verbose}", "--jit-min-calls=#{min_calls}", '-e', script],
+  def eval_with_jit(env = nil, script, verbose: 0, min_calls: 5, save_temps: false, timeout: JIT_TIMEOUT)
+    args = ['--disable-gems', '--jit-wait', "--jit-verbose=#{verbose}", "--jit-min-calls=#{min_calls}"]
+    args << '--jit-save-temps' if save_temps
+    args << '-e' << script
+    args.unshift(env) if env
+    EnvUtil.invoke_ruby(args,
       '', true, true, timeout: timeout,
     )
   end
Index: test/ruby/test_jit.rb
===================================================================
--- test/ruby/test_jit.rb	(revision 63272)
+++ test/ruby/test_jit.rb	(revision 63273)
@@ -564,6 +564,16 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L564
     end;
   end
 
+  def test_clean_so
+    Dir.mktmpdir("jit_test_clean_so_") do |dir|
+      code = "x = 0; 10.times {|i|x+=i}"
+      eval_with_jit({"TMPDIR"=>dir}, code)
+      assert_send([Dir, :empty?, dir])
+      eval_with_jit({"TMPDIR"=>dir}, code, save_temps: true)
+      assert_not_send([Dir, :empty?, dir])
+    end
+  end
+
   private
 
   # The shortest way to test one proc
@@ -606,7 +616,7 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L616
 
   # Run Ruby script with --jit-wait (Synchronous JIT compilation).
   # Returns [stdout, stderr]
-  def eval_with_jit(script, **opts)
+  def eval_with_jit(env = nil, script, **opts)
     stdout, stderr, status = super
     assert_equal(true, status.success?, "Failed to run script with JIT:\n#{code_block(script)}\nstdout:\n#{code_block(stdout)}\nstderr:\n#{code_block(stderr)}")
     [stdout, stderr]

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]