¿Cómo puedo esperar a que termine un subproceso desconectado en C++?Espere a que termine un subproceso desconectado en C++
No me importa un estado de salida, solo quiero saber si el hilo ha terminado o no.
Estoy tratando de proporcionar un contenedor síncrono alrededor de una herramienta thirdarty asíncrona. El problema es un accidente de condición de carrera extraño que implica una devolución de llamada. La progresión es:
- que llamo el thirdparty, y registrar una devolución de llamada
- cuando termina de terceros, que me notifica mediante la devolución de llamada - en un hilo separado tengo ningún control real sobre.
- Quiero que el hilo de (1) espere hasta que se llame (2).
Quiero envolver esto en un mecanismo que proporciona una llamada de bloqueo. Hasta el momento, no tengo:
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();
Por lo que yo puedo decir, esto debería funcionar, y lo hace normalmente, pero a veces se bloquea. Por lo que yo puedo determinar a partir del fichero de núcleo, yo creo que el problema es el siguiente:
- Cuando la devolución de llamada emite el final de m_done, el hilo espera despierta
- El hilo espera ahora se hace aquí, y Esperar es destruido. Todos los miembros de Wait se destruyen, incluidos el mutex y el cond.
- El hilo de devolución de llamada intenta continuar desde el punto de difusión, pero ahora está utilizando la memoria que se ha liberado, lo que da como resultado daños en la memoria.
- Cuando el hilo de devolución de llamada intenta regresar (por encima del nivel de mi pobre método de devolución de llamada), el programa falla (generalmente con un SIGSEGV, pero he visto SIGILL un par de veces).
He intentado muchos mecanismos diferentes para tratar de solucionar esto, pero ninguno de ellos resuelve el problema. Todavía veo choques ocasionales.
EDITAR: Más detalles:
Esto es parte de una aplicación masivamente multiproceso, por lo que la creación de una espera estática no es práctico.
Ejecuté una prueba, creando Esperar en el montón, y filtrando deliberadamente la memoria (es decir, los objetos de espera nunca se desasignan), y eso no ocasionó bloqueos. Así que estoy seguro de que se trata de un problema de espera que se desasignará demasiado pronto.
También he intentado una prueba con un sleep(5)
después del desbloqueo en wait
, y que también no produjo fallas. Sin embargo, odio confiar en un kludge así.
EDITAR: detalles de terceros:
Yo no creo que esto era relevante al principio, pero cuanto más lo pienso, más creo que es el verdadero problema:
El material thirdparty Mencioné, y por qué no tengo control sobre el hilo: esto es usando CORBA.
Por lo tanto, es posible que CORBA retenga una referencia a mi objeto por más tiempo de lo previsto.
Desafortunadamente, esto se encuentra en una aplicación de subprocesos múltiples, y realmente queremos objetos separados para cada uno, de lo contrario, nos ralentiza demasiado. – Tim
Además, si usamos un Wait estático, existe el problema de tratar de coordinar qué hilo debe reanudarse. – Tim
Ok, puedes hacer esto.Puede agregar un campo de refcount al objeto Wait, protegido por un mutex global. Comience el refcount en 2, y luego haga que la devolución de llamada y el mesero disminuyan el recuento cuando termine. Si el mutex global se convierte en su cuello de botella, existen otras soluciones más complicadas. –