c - ¿Está bien llamar a pthread_exit desde main?
winapi pthreads (3)
Cuando llamo pthread_exit
desde main
, el programa nunca llega a terminar. Esperaba que el programa terminara, ya que estaba saliendo del único hilo del programa, pero no funciona. Parece colgado.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int main(int argc, char *argv[])
{
printf("-one-/n");
pthread_exit(NULL);
printf("-two-/n");
}
Process Explorer muestra que el subproceso (único) está en el estado Wait:DelayExecution
.
De acuerdo con la documentación de pthread_exit
:
El proceso debe salir con un estado de salida de 0 después de que se haya terminado el último subproceso. El comportamiento será como si la implementación llamara a exit () con un argumento cero en el tiempo de finalización del subproceso.
Estoy usando Dev-C ++ v4.9.9.2 y pthreads-win32 v2.8.0.0 (vinculando contra libpthreadGC2.a
).
La biblioteca parece estar bien (por ejemplo, llamar pthread_self
o pthread_create
desde main
funciona bien).
¿Hay alguna razón para lo que se supone que no debo llamar a pthread_exit
desde main
?
Bueno, es definitivamente legal en la implementación de Linux de pthreads, mira la sección de notas en pthreads_exit . Afirma
Para permitir que otros subprocesos continúen la ejecución, el hilo principal debe terminar llamando a pthread_exit () en lugar de salir (3).
Además, un vistazo al código fuente aquí (tornea el final) muestra que se traduce aproximadamente a _endthread o _endthreadex. La documentación aquí para aquellos no hace mención de no llamarlo en el hilo inicial.
Este comportamiento completamente legal e intencionado. Todo el proceso solo finaliza cuando todos los hilos terminan o exit
se llama explícita o implícitamente.
Un retorno normal desde main
es equivalente a una llamada para exit
. Si finalizas main
con pthread_exit
estás diciendo explícitamente que quieres que los otros hilos continúen.
Al probar en Linux (versión 7.2.1511 (Core) de CentOS Linux) descubrí que, de hecho, el programa principal espera a que continúen los subprocesos "secundarios". Además, no pude pasar un código de retorno desde main, aunque se puede especificar como argumento para pthread_exit (), como dijo Raul arriba, siempre regresa con el código de salida 0:
retval=3;
pthread_exit(&retval);
También observamos un mensaje de error al usar el compilador de Clang (versión 3.4.2) y las opciones de desinfección:
==5811==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x7f4c090321d0 in thread T0
#0 0x7f4c08be3e29 in __interceptor_free (/home/karstenburger/tests/libc/pthread_exit_in_main/a+0x65e29)
#1 0x7f4c08333358 in free_key_mem (/lib64/libdl.so.2+0x1358)
#2 0x7f4c08745bc1 in __nptl_deallocate_tsd (/lib64/libpthread.so.0+0x7bc1)
#3 0x7f4c07771b38 in __libc_start_main (/lib64/libc.so.6+0x21b38)
#4 0x7f4c08bfa08c in _start (/home/karstenburger/tests/libc/pthread_exit_in_main/a+0x7c08c)
AddressSanitizer can not describe address in more detail (wild memory access suspected).
SUMMARY: AddressSanitizer: bad-free ??:0 __interceptor_free
==5811==ABORTING