pthread_mutex_lock __pthread_mutex_lock_full: утверждение не выполнено с надежным и 0x4000000 - PullRequest
3 голосов
/ 30 марта 2012

Я работаю над проектом на стороне сервера, который должен принимать более 100 клиентских подключений.

Это многопоточная программа, использующая boost :: thread.В некоторых местах я использую boost::lock_guard<boost::mutex> для блокировки общих данных членов.Существует также BlockingQueue<ConnectionPtr>, который содержит входные соединения.Реализация BlockingQueue:

template <typename DataType>
class BlockingQueue : private boost::noncopyable
{
public:
    BlockingQueue()
        : nblocked(0), stopped(false)
    {

    }

    ~BlockingQueue()
    {
        Stop(true);
    }

    void Push(const DataType& item)
    {
        boost::mutex::scoped_lock lock(mutex);
        queue.push(item);
        lock.unlock();
        cond.notify_one(); // cond.notify_all();
    }

    bool Empty() const
    {
        boost::mutex::scoped_lock lock(mutex);
        return queue.empty();
    }

    std::size_t Count() const
    {
        boost::mutex::scoped_lock lock(mutex);
        return queue.size();
    }

    bool TryPop(DataType& poppedItem)
    {
        boost::mutex::scoped_lock lock(mutex);
        if (queue.empty())
            return false;

        poppedItem = queue.front();
        queue.pop();

        return true;
    }

    DataType WaitPop()
    {
        boost::mutex::scoped_lock lock(mutex);

        ++nblocked;
        while (!stopped && queue.empty()) // Or: if (queue.empty())
            cond.wait(lock);
        --nblocked;

        if (stopped)
        {
            cond.notify_all(); // Tell Stop() that this thread has left
            BOOST_THROW_EXCEPTION(BlockingQueueTerminatedException());
        }

        DataType tmp(queue.front());
        queue.pop();

        return tmp;
    }

    void Stop(bool wait)
    {
        boost::mutex::scoped_lock lock(mutex);
        stopped = true;
        cond.notify_all();

        if (wait) // Wait till all blocked threads on the waiting queue to leave BlockingQueue::WaitPop()
        {
            while (nblocked)
                cond.wait(lock);
        }
    }

private:
    std::queue<DataType>          queue;
    mutable boost::mutex          mutex;
    boost::condition_variable_any cond;
    unsigned int                  nblocked;
    bool                          stopped;
};

Для каждого Connection существует ConcurrentQueue<StreamPtr>, который содержит входные потоки.Реализация ConcurrentQueue:

template <typename DataType>
class ConcurrentQueue : private boost::noncopyable
{
public:
    void Push(const DataType& item)
    {
        boost::mutex::scoped_lock lock(mutex);
        queue.push(item);
    }

    bool Empty() const
    {
        boost::mutex::scoped_lock lock(mutex);
        return queue.empty();
    }

    bool TryPop(DataType& poppedItem)
    {
        boost::mutex::scoped_lock lock(mutex);
        if (queue.empty())
            return false;

        poppedItem = queue.front();
        queue.pop();

        return true;
    }
private:
    std::queue<DataType> queue;
    mutable boost::mutex mutex;
};

При отладке программы все нормально.Но при нагрузочном тестировании с 50 или 100 или более клиентскими подключениями иногда оно прерывалось с

pthread_mutex_lock.c:321: __pthread_mutex_lock_full: Assertion `robust || (oldval & 0x40000000) == 0' failed.

. Я понятия не имею, что произошло, и его невозможно воспроизвести каждый раз.

Я гуглилмного, но не повезло.Пожалуйста, сообщите.

Спасибо.

Питер

1 Ответ

5 голосов
/ 25 июля 2012

0x40000000 - это FUTEX_OWNER_DIED - в заголовке futex.h есть следующие документы:

/*
 * The kernel signals via this bit that a thread holding a futex
 * has exited without unlocking the futex. The kernel also does
 * a FUTEX_WAKE on such futexes, after setting the bit, to wake
 * up any possible waiters:
 */
#define FUTEX_OWNER_DIED        0x40000000

Таким образом, утверждение, по-видимому, указывает на то, что поток, в котором находится блокировка, выходит изпо какой-то причине - существует ли способ, которым объект потока может быть уничтожен, пока он удерживает блокировку?

Еще одна вещь, которую нужно проверить, - это если у вас где-то есть повреждение памяти.Valgrind может быть инструментом, который может помочь вам в этом.

...