Как я могу дождаться окончания отдельного потока в C ++?
Меня не волнует состояние выхода, я просто хочу знать, закончился ли поток.
Я пытаюсь предоставить синхронную оболочку для асинхронного стороннего инструмента. Проблема в странном сбое состояния гонки с обратным вызовом. Прогрессия:
- Я звоню третьей стороне и регистрирую обратный звонок
- когда третья сторона завершает свою работу, она уведомляет меня об обратном вызове - в отдельном потоке у меня нет реального контроля.
- Я хочу, чтобы поток из (1) дождался вызова (2).
Я хочу заключить это в механизм, обеспечивающий блокирующий вызов. Пока что у меня есть:
class Wait {
public:
void callback() {
pthread_mutex_lock(&m_mutex);
m_done = true;
pthread_cond_broadcast(&m_cond);
pthread_mutex_unlock(&m_mutex);
}
void wait() {
pthread_mutex_lock(&m_mutex);
while (!m_done) {
pthread_cond_wait(&m_cond, &m_mutex);
}
pthread_mutex_unlock(&m_mutex);
}
private:
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
bool m_done;
};
// elsewhere...
Wait waiter;
thirdparty_utility(&waiter);
waiter.wait();
Насколько я могу судить, это должно работать, и обычно это происходит, но иногда происходит сбой. Насколько я могу определить из файла coref, я думаю, что проблема заключается в следующем:
- Когда обратный вызов сообщает о конце m_done, поток ожидания пробуждается
- Теперь поток ожидания завершен, и ожидание уничтожено. Все члены Уайта уничтожены, включая мьютекс и конд.
- Поток обратного вызова пытается продолжить с точки вещания, но теперь использует освобожденную память, что приводит к повреждению памяти.
- Когда поток обратного вызова пытается вернуться (выше уровня моего плохого метода обратного вызова), программа падает (обычно с SIGSEGV, но я видел SIGILL пару раз).
Я пробовал много разных механизмов, чтобы попытаться это исправить, но ни один из них не решил проблему. Я до сих пор вижу случайные сбои.
РЕДАКТИРОВАТЬ : Подробнее:
Это часть многопоточного приложения, поэтому создание статического ожидания нецелесообразно.
Я выполнил тест, создав ожидание в куче, и намеренно вытек из памяти (т. Е. Объекты ожидания никогда не освобождались), и это не привело к сбоям. Так что я уверен, что проблема в ожидании освобождения слишком рано.
Я также пробовал тест с sleep(5)
после разблокировки в wait
, и это также не вызывало сбоев. Хотя я ненавижу полагаться на такой клудж.
РЕДАКТИРОВАТЬ : Сведения о третьей стороне:
Сначала я не думал, что это актуально, но чем больше я об этом думаю, тем больше я думаю, что это настоящая проблема:
Третья сторона, которую я упомянул, и почему я не могу контролировать поток: это использование CORBA.
Таким образом, возможно, что CORBA удерживает ссылку на мой объект дольше, чем предполагалось.