2010-05-18 9 views
3

J'ai un simple serveur qui ressemble à ceci:Comment gérer correctement les signaux lorsque vous utilisez le modèle de fil de travail?

void *run_thread(void *arg) { 
    // Communicate via a blocking socket 
} 

int main() { 
    // Initialization happens here... 

    // Main event loop 
    while (1) { 
     new_client = accept(socket, ...); 
     pthread_create(&thread, NULL, &run_thread, *thread_data*); 
     pthread_detach(thread); 
    } 

    // Do cleanup stuff: 
    close(socket); 
    // Wait for existing threads to finish 
    exit(0); 
) 

Ainsi, lorsqu'un SIGINT ou SIGTERM est reçu, je dois sortir de la boucle d'événement pour obtenir le code de nettoyage. De plus, très probablement le thread principal attend l'appel de accept() donc il n'est pas capable de vérifier une autre variable pour voir si elle devrait se casser ;.

La plupart des conseils que j'ai trouvés étaient les suivants: http://devcry.blogspot.com/2009/05/pthreads-and-unix-signals.html (création d'un thread de traitement de signal spécial pour attraper tous les signaux et faire le traitement sur ceux-ci). Cependant, c'est la partie de traitement que je ne peux pas vraiment comprendre: comment puis-je dire au thread principal de revenir de l'appel de accept() et vérifier sur une variable externe pour voir si elle devrait casser ;?

Répondre

2

Habituellement j'attends select(listeninig-socket-here) pas sur accept(). accept() est généralement une méthode où un programme ne passe pas beaucoup de temps à attendre. Et quand j'attend dans select() et le signal SIGTERM est envoyé à ce fil (dans votre cas, c'est le fil principal) Je quitte de ce select et select renvoie interrupted system call.

+0

Merci, qui a travaillé. – ipartola

1

Je seconde skwllsp à son avis que vous devriez utiliser select appel au lieu d'accepter. Mais, ma suggestion supplémentaire est que vous suivez les conseils du blog dont vous avez posté le lien et créer un fil de manipulation de signal séparé et ignorer les signaux dans tous les autres threads. Ensuite, lorsque le signal est reçu dans le thread de traitement du signal, utilisez pthread_cancel pour annuler les autres threads. Lorsque vous utilisez pthread_cancel, si le thread qui est en cours d'annulation est en point d'annulation (select en est un), il sortira et entrera dans votre handler et vous pourrez nettoyer et quitter le thread.

Vous pouvez trouver plus d'informations sur ce here, here et here

+0

Oui, c'est ce que j'ai fini par faire. J'ai aussi utilisé pthread_cleanup_push et pthread_cleanup_pop. Fonctionne comme un charme. – ipartola

+0

Bon. En fait, l'idée et le concept de pthread_cancel sont brillants selon moi. :) – Jay