Hello,
The problem is that mutex is not got unlocked after the first unlock().
 
libstdc++ uses a wrapper for pthread called gthreads. This wrapper checks for the state of the mutex system. For example, pthread_mutex_unlock() is called in a following way:
 
static inline int
__gthread_mutex_unlock (__gthread_mutex_t *__mutex)
{
  if (__gthread_active_p ())
    return __gthrw_(pthread_mutex_unlock) (__mutex);
  else
    return 0;
}
 
The function __gthread_active_p() is an inline function which returns non-nullptr value is pthreads is available.
 
It seems that std::mutex::lock() in libstdc++ from Alpine Linux repos does not use ghtreads:
 
=> 0x00007ffff7eb6dde <+0>:     push   %rdx
   0x00007ffff7eb6ddf <+1>:     callq  0x7ffff7eaf550 <pthread_mutex_lock@plt>
   0x00007ffff7eb6de4 <+6>:     test   %eax,%eax
   0x00007ffff7eb6de6 <+8>:     je     0x7ffff7eb6def <_ZNSt5mutex4lockEv+17>
   0x00007ffff7eb6de8 <+10>:    mov    %eax,%edi
   0x00007ffff7eb6dea <+12>:    callq  0x7ffff7eb3f50 <_ZSt20__throw_system_errori@plt>
   0x00007ffff7eb6def <+17>:    pop    %rax
   0x00007ffff7eb6df0 <+18>:    retq 
 
std::mutex::lock() from glibc-compatible libstdc++ is not inlined by compiler during build, because it contains check for errors:
    void
    lock()
    {
      int __e = __gthread_mutex_lock(&_M_mutex);

      // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
      if (__e)
    __throw_system_error(__e);
    }
 
std::mutex::unlock() from glibc-compatible libstdc++ is inlined, because it does not contain anything but call to __gthread_mutex_lock():
    void
    unlock()
    {
      // XXX EINVAL, EAGAIN, EPERM
      __gthread_mutex_unlock(&_M_mutex);
    }
This is why pthread_mutex_lock() from musl is called, but pthread_mutex_unlock() is not.
 
Суббота, 21 ноября 2020, 18:51 +03:00 от Rich Felker <dalias@libc.org>:
 
On Sat, Nov 21, 2020 at 09:46:57AM +0300, a@saur0n.science wrote:
> Hello,
> Thanks for the fast response.
>
> I compiled binary under OpenSUSE towards glibc and started on Alpine
> Linux.

I think you mean just compiled normally on OpenSUSE without doing
anything related to musl at this point, but could you please conform
that that's the case?

Also, did you link libstdc++ statically or dynamically? Are you moving
any additional shared libraries over from the glibc system, or just
the application binary? Does it have any other libraries static linked
into it?

This is why I asked for full information on how you built it. The
answers to these questions determine what direction you should look
in.

musl provides some minimal level of glibc-ABI-compat for attempting to
get binaryware that you can't rebuild against musl to work. This
doesn't mean building binaries for glibc and attempting to use them
with musl is necessarily supported usage. It's possible that you're
doing something that just can't work, but it's also possible that
there are simple mistakes you could correct and get this working.

> I think it is not a problem because mutex is aggregated by a
> pointer.

I'm also not clear exactly what you mean by that.

> I am using gcc 10.2.1 20201028 [revision
> a78cd759754c92cecbf235ac9b447dcdff6c6e2f] installed from OpenSUSE
> reporitories.
>
> Unfortunately, I cannot post a "minimal working example", because
> the bug does not reproduce on a small programs.

This means the problem is in something you haven't shown or described.

> This is the internal state of the mutex which caused problems at the
> moment of second lock operation:

> (gdb) print gsMutex
> $1 = {<std::__mutex_base> = {_M_mutex = {__data = {__lock = 0, __count = 2147483664, __owner = 1, __nusers = 0, __kind = 0, __spins = 0, __elision = 0, __list = {
>          __prev = 0x0 , __next = 0x0 }}, __size = "\000\000\000\000\020\000\000\200\001", '\000' <repeats 30 times>, __align = -9223371968135299072}}, <No data fields>}

This is printing out a glibc data structure, which isn't going to be
meaningful.

Rich
 
 
——
Арсений