<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - atomic_compare_exchange_strong on shared_ptrs can deadlock"
   href="https://llvm.org/bugs/show_bug.cgi?id=27724">27724</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>atomic_compare_exchange_strong on shared_ptrs can deadlock
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libc++
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>All Bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>hboehm@google.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org, mclow.lists@gmail.com
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>This came out of a WG21 discussion a while ago that basically concluded that
all existing CAS implementations on shared_ptr are broken, though in different
ways.

The libc++ implementation in <memory> reads

template <class _Tp>
bool
atomic_compare_exchange_strong(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v,
shared_ptr<_Tp> __w)
{
    __sp_mut& __m = __get_sp_mut(__p);
    __m.lock();
    if (__p->__owner_equivalent(*__v))
    {
        *__p = __w;
        __m.unlock();
        return true;
    }
    *__v = *__p;
    __m.unlock();
    return false;
}

Both of the assignments are performed while holding a lock on __p.  But the
assignments may involve arbitrary destructor invocations, which may perform
atomic assignments hashing to the same location. Thus it could try to reacquire
the same lock, deadlocking with itself. Or it could participate in more
complicated deadlocks involving multiple threads.

Presumably the assignments need to be replaced by swaps to a local, which can
then be destroyed outside the critical section.</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>