J’apprends Pthreads et je me demandais quel était le meilleur moyen de tuer un tel object. Après avoir recherché des questions similaires, je n’étais pas en mesure de trouver une réponse “claire”, mais n’hésitez pas à me diriger vers des questions pertinentes.
Je travaille avec une petite application client-serveur, où le thread du serveur principal écoute sur un socket les connexions des clients. Chaque fois qu’un client se connecte, le serveur crée un nouveau thread effectuant des “travaux infinis” dans une boucle true. Maintenant, je veux arrêter cette boucle quand le même client envoie une demande “stop” sur le socket.
Comment implémenteriez-vous un tel comportement en sachant que les clients sont identifiés via un ID fourni dans chaque message de socket? Utilisation d’une variable partagée (entre le thread du serveur principal et les threads du serveur client) comme condition de test dans la boucle while. Vous utilisez une fonction PThread?
Il n’y a aucun moyen de tuer de force un seul thread POSIX; c’est intentionnel, par conception. Au lieu de cela, si votre thread doit pouvoir être arrêté par d’autres threads, vous devez concevoir le code qui y est exécuté pour en tenir compte. Pour ce faire, utilisez une variable de drapeau de sortie (protégée par un mutex) et une variable de condition.
Il y a aussi pthread_cancel
, qui peut être utilisé pour demander la sortie d’un thread. Pour l’utiliser correctement, vous devez configurer des gestionnaires de nettoyage avec pthread_cleanup_push
et / ou désactiver temporairement l’annulation avec pthread_setcancelstate
.
Vous ne devriez pas forcer le thread à sortir. Vous devez concevoir votre programme de telle sorte que la boucle while existe lorsque “stop” est envoyé.
Quelque chose comme:
while(strcmp(word, "stop")!=0){ word = read_word_from_socket(); ...... }
Vous pouvez concevoir votre serveur comme ceci:
typedef struct _client_data_buffer { char user_cmd[16]; /* Could be "CONTINUE" or "STOP" */ char* buffer; /* Client network data. You can use a fixed size buffer for this part also */ } client_data_buffer; /* client encode data before sending to the server */ size_t encode_client_data(client_data_buffer* data_buf, char* buf) { size_t serialized_bytes = 0; /* Can help for transmission errors checking */ /* Serialize the cmd */ memcpy(buf + serialized_bytes, data_buf->user_cmd, strlen(data_buf->user_cmd) + 1); serialized_bytes += strlen(data_buf->user_cmd) + 1; /* Serialize the data the client want to send to the server */ memcpy(buf + serialized_bytes, data_buf->buffer, strlen(data_buf->buffer) + 1); serialized_bytes += strlen(arch->nombre_arch) + 1; return serialized_bytes; } /* Server decode client data */ void decode_client_data(char* buf, client_data_buffer* data_buf) { /* Your decode here */ } int create_server(int port, char *address) { /* Create you server */ } void* thread_callback(void *client_data) { /* client socket descriptor */ int client_id = *(int *) client_data; client_data_buffer *some_user_data; char some_buffer[BUFFER_SIZE]; /* receiving data until STOP command is received */ while(1) { /* receive */ recv(client_id, some_buffer, BUFFER_SIZE, 0); /* decode some_buffer to some_user_data */ /* compare */ if (strcmp("STOP", some_user_data->user_cmd) == 0) { /* shutdown and close client socket and exit */ } else { /* Parse incoming data and do the job */ } } return NULL; } int main(int argc, char **argv) { int server_socket; int client_socket; int result; /* Crete our server */ server_socket = create_tcp_server (my_port_number, my_address); while (1) { pthread_t thread_id; client_socket = accept(server_socket, NULL ,NULL); result = pthread_create(&thread_id, NULL, thread_callback, (void *) client_socket); if (result != 0) { /* Handle errors with errno and exit */ } /* We don't care about the return status ---> avoid zombies and handling threads termination */ pthread_detach(thread_id); } exit (EXIT_SUCCESS); }