Newsgroup: it.comp.lang.c
Titolo: URGENTE Chiusura di un descrittore

Buongiorno a tutti,ho un problema grave(credo)...
Ho implementato un'applicazione Client/Server in 'C',ed ho riscontrato problemi
sulla parte SERVER relativi alla chiusura dei socket.
Una volta eseguita l'accept ,faccio una fork successivamete eseguo la close del
descrittore originale.
Una volta elaborate le n richieste,termino il processo figlio attraverso un
EXIT e di seguito chiudo il descrittore del nuovo socket.
Sulla prima chisura la close mi restituisce -1 con errno = 2 ENOENT "No such
file or directory",mentre sulla successiva chiusura la close mi restituisce -1
con errno = 9  EBADF "Bad file number".
Come posso risolvere questo problema ?.
Ringrazio anticipatamente tutti.
Alla prossima Cla.
-- 
Posted from  [213.213.71.66] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

> Come posso risolvere questo problema ?.
Inizia a postare un po' di estratti codice...
Ciao


Grazie Giovanni per il tuo interessamento adesso ti posto la parte riguradante
il loop di processi :
void SMS2_vMainLoop (void)
{
 int clilen;
 int childpid;
 int iErrno;
 int pid;
 int iResult;
 int error;
 char acMessage [LEN_MESSAGE];
 struct sockaddr_in cli_addr;
 /* Bind */ 
 
 if((error=bind(gptBase->tBase_SockCom->iDescSock,(struct
sockaddr*)&gptBase->tBase_SockCom->tServerSock,sizeof(gptBase->tBase_SockCom->tServerSock)))<0)
   {
    iErrno = errno;
 
    sprintf(acMessage,"Errore durante la Bind.[errno %d].\n",iErrno);
 
    TRACEOUT(acMessage);
 
    exit(SMS_ERROR);
    }
 else
    {    
     sprintf(acMessage,"Bind eseguita con successo.");
 
     TRACEOUT(acMessage);
    }    
 
 /* Listen */  
 
 if(error=listen(gptBase->tBase_SockCom->iDescSock,1) < 0)
   {
    iErrno = errno;
 
    sprintf(acMessage,"Errore durante la Listen.[errno %d]\n",iErrno);
 
    TRACEOUT(acMessage);  
 
    exit(SMS_ERROR);
   }
 else
   {    
    sprintf(acMessage,"Listen eseguita con successo.");
 
    TRACEOUT(acMessage);
   } 
 
 /* Ciclo per la ricezione ed invio msg verso il Client */  
 
 while(TRUE) 
   { 
     clilen = sizeof(cli_addr);
 
     gptBase->NuovoSocket = -1;
 
     gptBase->NuovoSocket=accept(gptBase->tBase_SockCom->iDescSock,(struct
sockaddr *)&cli_addr,&clilen);
 
     if(gptBase->NuovoSocket < 0) 
       { 	 
        iErrno = errno;
 
	sprintf(acMessage,"Errore durante l'Accept.[errno %d]\n",iErrno);
 
	TRACEOUT(acMessage);
       } 
 
    else
        /* Creo il processo figlio che si occupera' della gestione delle
risposte */
 
        childpid=fork();
 
        if(childpid < 0) 
          {
      	   sprintf(acMessage,"Prcesso figlio non creato. STOP! ");
 
	   TRACEOUT(acMessage);
 
           exit(SMS_ERROR);
          }	  
        else if(childpid == 0)
               {
	        iResult = SMS1_iCloseSock(gptBase->tBase_SockCom->iDescSock);
 
		if (iResult != SMS_SUCCESS)
		   {
	            sprintf(acMessage,"SMS1_iCloseSock Failed for parent process.\n");
	            TRACEOUT(acMessage);  
  		   }
		else
		   {
	            sprintf(acMessage,"SMS1_iCloseSock Success for parent
process.\n");
	            TRACEOUT(acMessage);		   
		   }    
 
		/* Funzione di smistamento richieste */ 
 
    	        iResult = SMS2_iManageRequest();
 
	        if(iResult) 
		  {
		   sprintf(acMessage,"SMS2_iManageRequest failed. \n");
 
		   TRACEOUT(acMessage);
 		  } 
		else   
		  {
		   sprintf(acMessage,"SMS2_iManageRequest OK.\n");
 
  	           TRACEOUT(acMessage);
		  } 
	       }
   } 
}
Questa funzione SMS2_iManageRequest() ha il compito di elaborare le richieste
inviate dal client attraverso il file.
La TRACEOUT è una macro da me definita utilizzata come Log.
Poco fa' ho modificato il codice mettendo la close prima di fare l'exit del 
processo figlio.
Forse il problema consiste nell'ereditarieta' dei descrittori dei file e di 
quello che riguarda l'ambiente del parent process nei confronti del child
process.
Una volta eseguita l'exit il figlio muore quindi come avrei modo di fare la
close
di un descrittore che non esiste piu',come fa il padre ad avere visione dei
file
aperti dal figlio ?.
Spero di non averti confuso le idee ti ringrazio nuovamnete.Claudio


void SMS2_vMainLoop (void)
{
 struct sockaddr_in cli_addr;
 int clilen;
 int childpid;
 int iErrno=0;
 int pid=0;
 int iResult=0;
 int error;
 char acMessage [LEN_MESSAGE];
 /* Eseguo la funzione Bind */ 
 
 if((error=bind(gptBase->tBase_SockCom->iDescSock,(struct
sockaddr*)&gptBase->tBase_SockCom->tServerSock,sizeof(gptBase->tBase_SockCom->tServerSock)))<0)
   {
    iErrno = errno;
 
    sprintf(acMessage,"Errore durante la Bind.[errno %d].\n",iErrno);
 
    TRACEOUT(acMessage);
 
    exit(SMS_ERROR);
    }
 else
    {    
     sprintf(acMessage,"Bind eseguita con successo.");
 
     TRACEOUT(acMessage);
    }    
 
 /* Eseguo la funzione Listen */  



La funzione SMS2_iManageRequest si occupa di elaborare il file inviato dal
client.
Ho provato a spostare la close prima dell'exit sul processo figlio l'errore non
lo
da piu'.Ora il problema e' comprendere il motivo per cui su tutti i testi e le
pagine web la close viene effettuata dopo l'exit.
Quando eseguo l'exit il processo figlio ha visibilita' dei descrittori aperti
aperti dal padre ?.
Grazie ancora Claudio.


 aperti dal padre ?.
Vedi sopra. Nella fork il figlio eredita i file descriptor aperti dal padre
al momento
della fork stessa, ma occhio che i descrittori vengono duplicati (man dup).
Poi ognuno va per la sua strada (se il figlio crea un nuovo file, il fd e'
tutto suo etc).
E' buona norma che il figlio chiuda i fd ereditati dal padre che non usera'
e viceversa.
Se ti capita sotto mano lo Stevens o il Comer dai un occhiata.
Hope this helps
Giovanni

Grazie per aver risposto,cmq lo Stevens "Unix sviluppo del software di 
networking" ce l'ho sottomano ed e' proprio in uno dei tanti esempi che ho
visto
effettuare la close del fd figlio da parte del padre.(prima l'exit e poi la
close).
Purtroppo non appena effettuo tale chiusura errno.h mi regala un bel 9(EBADF).
Non riesco a capire perche'.
Ho armato la SIGCHLD ed ho fatto una waitpid nel tentativo di fare la close
all'interno di questa signal(switch).L'errore riportato è sempre lo stesso.
Per quale motivo ?.
La funzione che esegue le richieste ha un (while(TRUE))all'interno ed esce 
solamente quando il client chiede esplicitamente la disconnessione, a quel
punto
eseguo l'exit ritornando al processo padre che come tu sottolinei dovrebbe 
chiudere il file descrittore del figlio.
Ora ci riprovo se ti viene qualche cosa in mente fammelo sapere.
Ancora un grazie Claudio.
