[prev in list] [next in list] [prev in thread] [next in thread] 

List:       ruby-core
Subject:    [ruby-core:105048] [Ruby master Bug#18126] Process termination three seconds after thread terminatio
From:       "mame (Yusuke Endoh)" <noreply () ruby-lang ! org>
Date:       2021-08-23 5:29:47
Message-ID: redmine.issue-18126.20210823052946.18 () ruby-lang ! org
[Download RAW message or body]

Issue #18126 has been reported by mame (Yusuke Endoh).

----------------------------------------
Bug #18126: Process termination three seconds after thread termination dumps core
https://bugs.ruby-lang.org/issues/18126

* Author: mame (Yusuke Endoh)
* Status: Open
* Priority: Normal
* Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN
----------------------------------------
The following code occasionally dumps core.

```
3000.times{Thread.new{}}
sleep 2.99
```

```
$ ruby test.rb
[BUG] Segmentation fault at 0x0000000000000440
ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-linux]

$
```

An internal batch script in our company aborts randomly due to this issue.

@ko1 and I investigated the issue. When a Ruby Thread terminates, its internal \
pthread is reused by another Ruby Thread if a new Ruby Thread is created within three \
minutes. If it is not reused, the pthread frees sigaltstack memory (by using xfree) \
and terminates. However, if the Ruby process starts terminating while the pthread is \
waiting for three minutes, Ruby VM and GC is destructed. After that, xfree is no \
longer available, which leads to the segfault.

A simple solution is to use malloc/free instead of Ruby's xmalloc/xfree, but it would \
be better to trigger GC when memory allocation fails.

```diff
diff --git a/signal.c b/signal.c
index 764031e78a..f0ed7f90d4 100644
--- a/signal.c
+++ b/signal.c
@@ -560,7 +560,9 @@ rb_allocate_sigaltstack(void)
     if (!rb_sigaltstack_size_value) {
        rb_sigaltstack_size_value = rb_sigaltstack_size();
     }
-    return xmalloc(rb_sigaltstack_size_value);
+    void *altstack = malloc(rb_sigaltstack_size_value);
+    if (!altstack) rb_memerror();
+    return altstack;
 }

 /* alternate stack for SIGSEGV */
diff --git a/vm_core.h b/vm_core.h
index 5db3080b43..2962356212 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -136,7 +136,7 @@
 void *rb_allocate_sigaltstack(void);
 void *rb_register_sigaltstack(void *);
 #  define RB_ALTSTACK_INIT(var, altstack) var = rb_register_sigaltstack(altstack)
-#  define RB_ALTSTACK_FREE(var) xfree(var)
+#  define RB_ALTSTACK_FREE(var) free(var)
 #  define RB_ALTSTACK(var)  var
 #else /* noop */
 #  define RB_ALTSTACK_INIT(var, altstack)
```




-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic