Bug #12290
closedPossible segfault with Thread#name=
Description
Ruby 2.3 added a Thread#name=, which may segfault when used incorrectly. This little program:
class SubClassedThread < Thread
def initialize()
self.name = 'foo'
super do
yield
end
end
end
SubClassedThread.new {}
Causes a segfault with both Ruby 2.3 (ruby 2.3.0p0 (2015-12-25 revision 53290)) and ruby-2.4.0-dev (ruby 2.4.0dev (2016-04-15 trunk 54594)). Moving the line that assignes the name in the block passed to super resolves the issue. Even thought there is a workaround, it shouldn't be possible to trigger a segfault from a script imho.
The relevant lines of the backtrace
/lib/i386-linux-gnu/i686/cmov/libpthread.so.0(pthread_setname_np+0x50) [0xf739ded0]
ruby(rb_thread_setname+0x95) [0xf755dc85] thread.c:2797
The system is a default Debian Jessie (32bit), with libc version 2.19-18+deb8u4.
Files
Updated by herwinw (Herwin Quarantainenet) almost 8 years ago
And of course the backtrace can be improved when installing the debugging symbols for libc
/lib/i386-linux-gnu/i686/cmov/libpthread.so.0(pthread_setname_np+0x50) [0xf73e0ed0] ../nptl/sysdeps/unix/sysv/linux/pthread_setname.c:49
The exact source can be downloaded from https://packages.debian.org/jessie/libc6 (keep in mind that the original source and the packages have to be downloaded separately, and be combined.
Updated by herwinw (Herwin Quarantainenet) almost 8 years ago
And since it's pretty easy to get the relevant source on a running debian system:
int
pthread_setname_np (th, name)
pthread_t th;
const char *name;
{
const struct pthread *pd = (const struct pthread *) th;
...
#define FMT "/proc/self/task/%u/comm"
char fname[sizeof (FMT) + 8];
sprintf (fname, FMT, (unsigned int) pd->tid);
Line 49 is the last line, and this is indeed the first part where a member of td is queried.
Updated by herwinw (Herwin Quarantainenet) almost 8 years ago
And this is the simplest solution I could think of. It throws an exception, which is a better way to react than a segfault. Making it actually work would of course be even better.
Updated by herwinw (Herwin Quarantainenet) almost 8 years ago
That patch still segfaulted when using self.name = nil
. Version 2 attached.
Updated by nobu (Nobuyoshi Nakada) almost 8 years ago
- Status changed from Open to Closed
Applied in changeset r54598.
thread.c: must be initialized to set name
- thread.c (get_initialized_threadptr): extract ensuring that the
thread is initialized. - thread.c (rb_thread_setname): thread must be initialized to set
the name. [ruby-core:74963] [Bug #12290]
Updated by nobu (Nobuyoshi Nakada) almost 8 years ago
- Description updated (diff)
- Backport changed from 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN to 2.1: DONTNEED, 2.2: DONTNEED, 2.3: REQUIRED
Updated by nagachika (Tomoyuki Chikanaga) almost 8 years ago
- Backport changed from 2.1: DONTNEED, 2.2: DONTNEED, 2.3: REQUIRED to 2.1: DONTNEED, 2.2: DONTNEED, 2.3: DONE
ruby_2_3 r54607 merged revision(s) 54598,54600.