Come posso attendere il completamento di un thread separato in C++?Attendere il completamento di un thread staccato in C++
Non mi interessa uno stato di uscita, voglio solo sapere se il thread è finito.
Sto provando a fornire un wrapper sincrono attorno a uno strumento asincrono di terze parti. Il problema è uno strano incidente di condizioni di gara che coinvolge un callback. La progressione è:
- io chiamo di terze parti, e registrare un callback
- quando le finiture di terze parti, che mi avvisa usando il callback - in un thread indipendente non ho alcun reale controllo.
- Voglio che il thread da (1) attenda fino a quando viene chiamato (2).
Voglio avvolgere questo in un meccanismo che fornisce una chiamata di blocco. Finora, ho:
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();
Per quanto posso dire, questo dovrebbe funzionare, e di solito lo fa, ma a volte si blocca. Per quanto posso determinare dal corefile, la mia ipotesi per quanto riguarda il problema è questo:
- Quando il callback trasmette la fine del m_done, il filo di attesa si sveglia
- Il filo di attesa è ormai fatto qui, e Wait è distrutto. Tutti i membri di Wait vengono distrutti, inclusi il mutex e cond.
- Il thread di richiamata tenta di continuare dal punto di trasmissione, ma ora utilizza la memoria rilasciata, che provoca il danneggiamento della memoria.
- Quando il thread di richiamata tenta di tornare (oltre il livello del mio metodo di callback non valido), il programma si blocca (di solito con un SIGSEGV, ma ho visto SIGILL un paio di volte).
Ho provato un sacco di meccanismi diversi per provare a risolvere questo problema, ma nessuno di loro ha risolto il problema. Vedo ancora incidenti occasionali.
EDIT: Maggiori dettagli:
Questo fa parte di un programma in maniera massiccia multithread, in modo da creare un Wait statico non è pratico.
Ho eseguito un test, creando Wait sull'heap e filtrando deliberatamente la memoria (ad esempio, gli oggetti Wait non sono mai stati deallocati) e non si sono verificati arresti anomali. Quindi sono sicuro che sia un problema di attesa che viene presto rilasciato.
Ho anche provato un test con uno sleep(5)
dopo lo sblocco in wait
e anche questo non ha causato arresti anomali. Odio fare affidamento su un kludge come quello però.
EDIT: thirdParty dati:
io non credo che questo era rilevante in un primo momento, ma più ci penso, più credo che sia il vero problema:
La roba di terze parti Ho menzionato, e perché non ho alcun controllo sul thread: questo sta usando CORBA.
Quindi, è possibile che CORBA tratti un riferimento al mio oggetto più a lungo del previsto.
Sfortunatamente, questo è in un'app molto multithreaded, e vogliamo davvero separare gli oggetti Wait per ognuno - altrimenti ci rallenta troppo. – Tim
Inoltre, se usiamo un Wait statico, c'è il problema di provare a coordinare quale thread deve riprendere. – Tim
Ok, puoi farlo.È possibile aggiungere un campo Refcount all'oggetto Wait, protetto da un mutex globale. Inizia il conto alla rovescia al 2, e poi hai il callback e il cameriere diminuisce entrambi il refcount una volta terminato. Se il mutex globale diventa il collo di bottiglia, ci sono altre soluzioni più complicate. –