Tengo un hilo principal que crea hilos secundarios para realizar varias tareas. Hay un subproceso secundario que tiene la tarea de informar sobre el estado cada 100 s.
Mi mecanismo actual para detener el hilo es observar un booleano global. Algo así
Hilo hijo
void* ReportThread(bool* operation) { while(*operation) { // do its reporting task // ........ int counter = 0; while( counter < 100 && operation ) { // let it sleep for 1 seconds and wake up to check sleep(1); sleepCounter += 1; } } }Subproceso principal (principal):
bool operation = false; int main(){ pthread_t tid; err = pthread_create(&tid), NULL, &ReportThread, &operation); printf("Please input esc to end operation \n"); while ((ch = getchar()) != 27); operation =true; pthread_join(tid,NULL); return 0; }El problema:
Saludos
Esta parte
while( counter < 100 || operation ) { // let it sleep for 1 seconds and wake up to check sleep(1); sleepCounter += 1; }Está Mal.
Primero asumo que sleepCounter += 1; es realmente un error tipográfico y que debería ser:
while( counter < 100 || operation ) { // let it sleep for 1 seconds and wake up to check sleep(1); counter += 1; } Entonces, el problema es que incluso si operation se establece en falso por algún otro subproceso, el while no finalizará hasta que el counter llegue a 100.
El código debe ser
while( counter < 100 && operation ) { // let it sleep for 1 seconds and wake up to check sleep(1); counter += 1; } Además, en main nunca estableces operation en falso. ¿Otro error tipográfico?
No necesitas dos bucles while . Y si desea configurar un temporizador, use las funciones de tiempo para ello, porque sleep es un punto de cancelación y no se garantiza que el sleep realmente duerma esa cantidad de tiempo.
Ejemplo:
void* ReportThread(void *args) { time_t start = time(NULL); time_t now; bool *operation = (bool*) args; while (*operation) { //while active now = time(NULL); //get current time if (now - start >= 100) { //if the threshold is exceeded start = now; //reset timer //and probably do other stuff } sleep(1); //sleep for one second } return NULL; } El ejemplo anterior tiene un retraso máximo de un segundo, lo que significa que si establece operation en false justo en el momento en que el subproceso entró en el estado de suspensión, debe esperar hasta que vuelva sleep , solo entonces reconocerá el estado modificado. El ejemplo también tiene la ventaja de que puede modificar fácilmente el valor del umbral (ya que depende del tiempo 'real', en lugar de un contador y un tiempo de sueño no preciso).
Por cierto. la operation variable debe ser un booleano atómico o estar protegida por un mutex (ya que se accede a ella desde diferentes subprocesos).
Para responder a las preguntas de su problema:
sleep es un punto de cancelación, lo que significa que se interrumpe si el proceso maneja una señal (ver man pthreads - sección Puntos de cancelación ).En Linux, la cancelación se implementa mediante señales. Bajo la implementación de subprocesos NPTL, la primera señal en tiempo real (es decir, la señal 32) se usa para este propósito. En LinuxThreads, se usa la segunda señal en tiempo real, si las señales en tiempo real están disponibles; de lo contrario, se usa SIGUSR2.
¡No puede usar pthread_cancel sobre pthread_join ! Tiene que usar pthread_join en cualquier caso (descrito en detalle en la página del manual).
No sé si esto solucionará todos sus problemas, pero es demasiado para un comentario. Un problema, la firma de la función ReportThread es incorrecta. Debería ser:
void* ReportThread(void* args);Y luego en esa función necesitas hacer algo como:
void* ReportThread(void* args) { bool* operation = (bool*)args; while(*operation) { ... } } No estoy seguro de cómo está funcionando en este momento, pero su compilador debería al menos emitir una advertencia al intentar convertir un tipo bool* en un bool .
También tenga en cuenta las condiciones de carrera en operation .