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

ruby-changes:53780

From: k0kubun <ko1@a...>
Date: Tue, 27 Nov 2018 00:12:36 +0900 (JST)
Subject: [ruby-changes:53780] k0kubun:r65999 (trunk): process.c: avoid dlclose before exec

k0kubun	2018-11-27 00:12:31 +0900 (Tue, 27 Nov 2018)

  New Revision: 65999

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

  Log:
    process.c: avoid dlclose before exec
    
    because JIT-ed code may still be on stack at this time, unlike
    in ruby_cleanup().
    
    This hopes to fix: (take 2)
    http://ci.rvm.jp/results/trunk-mjit-wait@silicon-docker/1480207

  Modified files:
    trunk/eval.c
    trunk/internal.h
    trunk/mjit.c
    trunk/process.c
Index: eval.c
===================================================================
--- eval.c	(revision 65998)
+++ eval.c	(revision 65999)
@@ -233,7 +233,7 @@ ruby_cleanup(volatile int ex) https://github.com/ruby/ruby/blob/trunk/eval.c#L233
 	}
     }
 
-    mjit_finish(); /* We still need ISeqs here. */
+    mjit_finish(TRUE); /* We still need ISeqs here. */
 
     ruby_finalize_1();
 
Index: mjit.c
===================================================================
--- mjit.c	(revision 65998)
+++ mjit.c	(revision 65999)
@@ -134,12 +134,13 @@ init_list(struct rb_mjit_unit_list *list https://github.com/ruby/ruby/blob/trunk/mjit.c#L134
    because node of unit_queue and one of active_units may have the same unit
    during proceeding unit. */
 static void
-free_list(struct rb_mjit_unit_list *list)
+free_list(struct rb_mjit_unit_list *list, int close_handle_p)
 {
     struct rb_mjit_unit *unit = 0, *next;
 
     list_for_each_safe(&list->head, unit, next, unode) {
         list_del(&unit->unode);
+        if (!close_handle_p) unit->handle = NULL; /* Skip dlclose in free_unit() */
         free_unit(unit);
     }
     list->length = 0;
@@ -787,9 +788,12 @@ mjit_child_after_fork(void) https://github.com/ruby/ruby/blob/trunk/mjit.c#L788
 
 /* Finish the threads processing units and creating PCH, finalize
    and free MJIT data.  It should be called last during MJIT
-   life.  */
+   life.
+
+   If close_handle_p is TRUE, it calls dlclose() for JIT-ed code. So it should be FALSE
+   if the code can still be on stack. ...But it means to leak JIT-ed handle forever (FIXME). */
 void
-mjit_finish(void)
+mjit_finish(int close_handle_p)
 {
     if (!mjit_enabled)
         return;
@@ -827,9 +831,9 @@ mjit_finish(void) https://github.com/ruby/ruby/blob/trunk/mjit.c#L831
     xfree(pch_file); pch_file = NULL;
 
     mjit_call_p = FALSE;
-    free_list(&unit_queue);
-    free_list(&active_units);
-    free_list(&compact_units);
+    free_list(&unit_queue, close_handle_p);
+    free_list(&active_units, close_handle_p);
+    free_list(&compact_units, close_handle_p);
     finish_conts();
 
     mjit_enabled = FALSE;
Index: process.c
===================================================================
--- process.c	(revision 65998)
+++ process.c	(revision 65999)
@@ -2944,7 +2944,7 @@ rb_f_exec(int argc, const VALUE *argv) https://github.com/ruby/ruby/blob/trunk/process.c#L2944
 
     execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
     eargp = rb_execarg_get(execarg_obj);
-    if (mjit_enabled) mjit_finish(); /* do not leave files or leak children */
+    if (mjit_enabled) mjit_finish(FALSE); /* avoid leaking resources, and do not leave files. XXX: JIT-ed handle can leak after exec error is rescued. */
     before_exec(); /* stop timer thread before redirects */
     rb_execarg_parent_start(execarg_obj);
     fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
Index: internal.h
===================================================================
--- internal.h	(revision 65998)
+++ internal.h	(revision 65999)
@@ -1634,12 +1634,12 @@ VALUE rb_math_sqrt(VALUE); https://github.com/ruby/ruby/blob/trunk/internal.h#L1634
 extern int mjit_enabled;
 VALUE mjit_pause(int wait_p);
 VALUE mjit_resume(void);
-void mjit_finish(void);
+void mjit_finish(int close_handle_p);
 #else
 #define mjit_enabled 0
 static inline VALUE mjit_pause(int wait_p){ return Qnil; } /* unreachable */
 static inline VALUE mjit_resume(void){ return Qnil; } /* unreachable */
-static inline void mjit_finish(void){}
+static inline void mjit_finish(int close_handle_p){}
 #endif
 
 /* newline.c */

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

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