Visualizzazione dei risultati da 1 a 5 su 5
  1. #1

    [C] - utilizzo di signal

    Salve a tutti.

    Ho il seguente problema:

    Sto sviluppando un'applicazione client/server in C sotto linux.

    Il client si collega al server e gli comunica un nick. Il server ricevuto il nick, provvede ad accodare il client in una CODA di client incrementando una variabile globale che rappresenta il numero di connessioni attuali. Fin qui non ci piove. (Ovviamente queste due operazioni sono atomiche, e quindi ho utilizzato un semaforo).

    Quando invece un client si disconnette, sempre atomicamente, il server provvede ad eliminare il client dalla coda e decrementare il numero di connessioni attuali.
    Il problema nasce nel momento in cui il client sta effettuando una qualsiasi operazione che viene gestita dal thread accettazione, perchè nel momento in cui il client si trova a dover interagire con il thread, e viene generata una interruzione (CTRL+C), il client non cattura il segnale, e quindi non elimina l'utente dalla coda, e non decrementa il numero di connessioni al server. Cioè è come se ignorasse completamente il CTRL+C, però nel frattempo il client si disconnette, cioè termina la sua esecuzione.

    Vi posto un pò di codice, può essere che si capisca dov'è il problema.


    Ora nel client ho il seguente codice:

    codice:
    ....
    signal(SIGINT, client_int);
    ...
    
    void client_int(int signum)
    {  
    	//Handler per l'interruzione del client
    
           
    
    	// Manda il messaggio "int" al server
    	write_socket( sock_fd, "int");
    	// Chiude il socket
    	close(sock_fd);
    	exit(1);
    }
    Se il thread non viene creato e faccio CTRL+C dal client, tutto funziona.
    Se il thread viene creato e utilizzo il menu per uscire, chiamando la funzione client_int, tutto funziona
    Ma se il thread viene creato e faccio CTRL+C dal client, il client si disconnette, ma non viene gestito il segnale. (Perchè???)

    Nel server ho un thread con il seguente codice:
    codice:
    void *accettazione(void *conn_fd)
    {
        char buffer[1024];
        int fd = (int)conn_fd;
        while(1)
        {
           read_socket(fd, buffer);
           if(strcmp(buffer,"new")==0)
           {
               //Crea una nuova partita
           }
           ...
           // Ci sono altri else if, per altri messaggi di scambio con il client
           ....
           else if(strcmp(buffer,"int")==0)
    	{
    		pthread_mutex_lock(&m_coda);					
    			eliminaNodo(&coda, fd);
    			nConnessioni--;
    		pthread_mutex_unlock(&m_coda);
    	}
        }
    }
    Spero di essermi spiegato... Aiutatemi voi!

  2. #2
    ho capito dov'è l'errore.

    quando il server accetta la connessione del client, e crea il thread di accettazione che gli mostra il menu di gioco, e l'utente sceglie una delle opzioni, non arriva il messaggio "int\0" al server, cioè è come se non facesse in tempo a prendere il messaggio... questo lo vedo perchè ho fatto una stampa di buffer nel server, e questa non è mai "int\0", a meno che il client non scelga l'opzione di uscita che chiama automaticamente client_int che poi a sua volta scriver al server "int\0", e quindi il server dealloca il nodo.

    Come risolvo?

  3. #3
    codice:
    void client_int(int signum)
    {  
    	//Handler per l'interruzione del client
    
           
    
    	// Manda il messaggio "int" al server
    	write_socket( sock_fd, "int"); 
    	// Chiude il socket
    	close(sock_fd);
    	exit(1);
    }
    Con le stampe della stringa dei messaggi, sono riuscito a capire che il problema è nella write.
    write_socket( sock_fd, "int");
    Sì, il problema e proprio lì... e come se non riuscisse a scrivere tutto, come se l'interruzione non desse il "tempo" alla write di scrivere, infatti scrive solo "i" che è la prima lettera di "int\0", ma perchè???

  4. #4
    Utente di HTML.it L'avatar di Ed_Bunker
    Registrato dal
    Jul 2003
    Messaggi
    1,119
    Premesso che spiegare e dettagliare meglio l'architettura dell'applicazione sarebbe la prima cosa da fare...
    Fai riferimento a sigaction piuttosto che a signal il cui utilizzo mi sembrava essere "deprecated".
    La gestione dei segnali in ambito multithread puo' creare a problemi se non si comprende bene cosa accade quando viene inviato un segnale all'intero processo (Come nel caso di ctrlC).
    Parti dandoti un'occhiata ad un po' di documentazione.

    In situazioni come queste si puo', ad esempio, fare in modo che vi sia un solo thread deputato alla gestione dei segnali.
    In tal caso e' sufficiente bloccare tutti i segnali (Agendo sulla signal mask), creare i thread (Che erediteranno la maschera dei segnali) e quindi modificare la maschera in modo da gestire "personalmente" i segnali di proprio interesse in uno solo di tali thread.

  5. #5
    Ho notato che se utilizzo
    codice:
       write(sock_fd, "int\0", 4*sizeof(char));
    al posto di write_socket, funziona. E' proprio la write socket che non riesce a scrivere tutti i caratteri...

    Ecco la write_socket
    codice:
    ssize_t write_socket(int fd, char *stringa)
    {
    	int i = 0;
    	// Incrementa i finchè la write va a buon fine e non finisce tutti i caratteri della stringa
    	while( write(fd, &stringa[i], sizeof(char)) > 0 && stringa[i] != '\0' )
    		i++;
    	return (ssize_t)i;
    }
    Cosa c'è di sbagliato in questa funzione? Mi sto preoccupando, visto che viene utilizzata in tutto il progetto.
    Non vorrei che sbagliasse in altri punti del programma e nemmeno me ne accorgo...

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.