Bug 19481 – Aborting from local/libphobos/libdruntime/core/sync/mutex.d(95) Error: pthread_mutex_init failed.

Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P1
Component
druntime
Product
D
Version
D2
Platform
Other
OS
Solaris
Creation time
2018-12-12T19:00:24Z
Last change time
2019-10-14T03:07:38Z
Keywords
pull
Assigned to
No Owner
Creator
Iain Buclaw

Comments

Comment #0 by ibuclaw — 2018-12-12T19:00:24Z
Thread._locks is not suitably aligned. --- __gshared align(Mutex.alignof) void[__traits(classInstanceSize, Mutex)][2] _locks; static void initLocks() @nogc { foreach (ref lock; _locks) { lock[] = typeid(Mutex).initializer[]; (cast(Mutex)lock.ptr).__ctor(); } } --- _locks should be aligned to pthread_mutex_t, not pointer size.
Comment #1 by kinke — 2018-12-12T20:00:22Z
`Mutex.m_hndl.alignof` (as it's a CRITICAL_SECTION for Windows) doesn't work, as it's private. There's no way to get the class instance alignment, is there? Plus anything > 16 bytes isn't guaranteed by the GC either AFAIK. So class alignments seem a bit problematic in general.
Comment #2 by ibuclaw — 2018-12-12T20:28:24Z
(In reply to kinke from comment #1) > `Mutex.m_hndl.alignof` (as it's a CRITICAL_SECTION for Windows) doesn't > work, as it's private. > I was thinking of just doing as a quick hack. --- version (Windows) { import core.sys.windows.winbase : CRITICAL_SECTION; enum Mutex_alignof = CRITICAL_SECTION.alignof; } else version (Posix) { import core.sys.posix.sys.types : pthread_mutex_t; enum Mutex_alignof = pthread_mutex_t.alignof; } --- Alternatively... class Mutex { enum alignsize = Mutex.m_hndl.alignof; // ... } > There's no way to get the class instance alignment, is there? Plus anything > > 16 bytes isn't guaranteed by the GC either AFAIK. So class alignments seem > a bit problematic in general. No, there isn't a way to do that. I'm currently waiting to hear back if explicitly setting the alignment to 8 fixes the failure on SPARC/Solaris.
Comment #3 by ibuclaw — 2018-12-13T21:29:36Z
According to response, the alignment of _locks[0] is fine, _locks[1] is the problem. >>> Unfortunately, this doesn't work: the first time through, _locks[0] was already 8-byte aligned and everything worked fine. This remained when using align(8) instead. However, Mutex is 44 bytes on 32-bit Solaris/x86, so again _locks[1] lands on a non-8 byte boundary and pthread_mutex_init fails. I tried rouding up the size of the _locks array members to a multiple of 8, but that let the constructor already fail the first time through where _d_arraycopy checks that the right amount of data is copied: _d_arraycopy -> rt.util.array.enforceRawArraysConformable -> rt.util.array._enforceSameLength <<<
Comment #4 by kinke — 2018-12-13T22:30:01Z
Argh, it's an array, and class instances aren't padded... - the error stems from the manual initialization in `initLocks()`, right? That should be easily adaptable; the ctor only gets the `this` pointer and shouldn't have any idea about the actual size.
Comment #5 by ibuclaw — 2018-12-13T23:03:35Z
(In reply to kinke from comment #4) > Argh, it's an array, and class instances aren't padded... - the error stems > from the manual initialization in `initLocks()`, right? That should be > easily adaptable; the ctor only gets the `this` pointer and shouldn't have > any idea about the actual size. Correct. This line: __gshared align(Mutex.alignof) void[__traits(classInstanceSize, Mutex)][2] _locks; The size should be rounded up to a suitable align boundary, then this line: lock[] = typeid(Mutex).initializer[]; The slice assignment is adjusted to only initialize up to __traits(classInstanceSize, Mutex). So we end up with something that looks like: --- version (Windows) { import core.sys.windows.winbase : CRITICAL_SECTION; enum lockAlign = CRITICAL_SECTION.alignof; } else version (Posix) { import core.sys.posix.sys.types : pthread_mutex_t; enum lockAlign = pthread_mutex_t.alignof; } enum mutexInstanceSize = __traits(classInstanceSize, Mutex) enum lockAlignedSize = (mutexInstanceSize + lockAlign - 1) & ~(lockAlign - 1); __gshared align(lockAlign) void[lockAlignedSize][2] _locks; static void initLocks() @nogc { foreach (ref lock; _locks) { lock[0 .. mutexInstanceSize] = typeid(Mutex).initializer[]; (cast(Mutex)lock.ptr).__ctor(); } } --- I don't think `align(lockAlign)` is really necessary based on feedback, but it covers us "just incase".
Comment #6 by kinke — 2018-12-13T23:47:04Z
Yep, looks fine, and definitely keep the `align(mutexAlign)`. :) - You could get away with a single `alignedMutexInstanceSize` enum (and no `mutexInstanceSize`) by using `const init = typeid(Mutex).initializer; lock[0 .. init.length] = init[];`.
Comment #7 by dlang-bot — 2019-03-16T17:34:35Z
@ibuclaw updated dlang/druntime pull request #2411 "Fix Issue 19481: mutex.d(95) Error: pthread_mutex_init failed" fixing this issue: - Fix Issue 19481: mutex.d(95) Error: pthread_mutex_init failed https://github.com/dlang/druntime/pull/2411
Comment #8 by dlang-bot — 2019-03-31T21:33:52Z
@ibuclaw created dlang/druntime pull request #2534 "[dmd-cxx] Fix Issue 19481: mutex.d(95) Error: pthread_mutex_init failed" fixing this issue: - Fix Issue 19481: mutex.d(95) Error: pthread_mutex_init failed https://github.com/dlang/druntime/pull/2534
Comment #9 by dlang-bot — 2019-04-01T10:43:58Z
dlang/druntime pull request #2534 "[dmd-cxx] Fix Issue 19481: mutex.d(95) Error: pthread_mutex_init failed" was merged into dmd-cxx: - 505e88f5b2983ffc286ed7c66442480433db3c9e by Iain Buclaw: Fix Issue 19481: mutex.d(95) Error: pthread_mutex_init failed https://github.com/dlang/druntime/pull/2534
Comment #10 by ibuclaw — 2019-04-01T10:49:30Z
Not fixed, as patch still not in master.
Comment #11 by dlang-bot — 2019-10-14T03:07:38Z
dlang/druntime pull request #2411 "Fix Issue 19481: mutex.d(95) Error: pthread_mutex_init failed" was merged into master: - ebe147ca8b63f8c59f797a93c492bc4e2e775416 by Iain Buclaw: Fix Issue 19481: mutex.d(95) Error: pthread_mutex_init failed https://github.com/dlang/druntime/pull/2411