View Full Version : [C]problemi di visibilità variabili globali tra processi padri e figli..
santaclause83
20-09-2007, 17:38
ho una variabile
t_newclient ** clienti;
che dichiaro fuori dal main come variabile globale,questa è un puntatore a tutti i puntatori a delle strutture di tipo t_newclient;
queste dentro hanno un campo nome e un campo pid
quando un cliente si connette,nel campo t_newclient.pid viene aggiornato il pid del cliente e quando se ne va il suo pid viene messo a 0.
questo perchè nel caso arrivi al server un SIGINT questo nel gestore scorre la struttura dati e tutti i pid che non sono a 0 vengono avvertiti.
PROBLEMA:
il cliente se ne va e il pid viene azzerato....se dopo però lancio un interruzione al server questo nella struttura dati trova ancora il pid del cliente e la kill sul pid che non esiste più dà errore
la struttura dati è globale,dichiarata fuori dal main,inizializzata appena dentro il main,a questa possono accedere anche i processi figli(ognuno tratta un cliente differente e si preoccupa di rimuovere il pid quando se ne va)
non capisco perchè non debba rimanere aggiornata quando il gestore la va a scorrere.....
ilsensine
20-09-2007, 17:42
Fammi capire...lanci i child con fork e pretendi che accedano alla memoria del padre?
santaclause83
20-09-2007, 18:46
il problema è che se arriva un SIGINT al server,questo prima di uscire completamente dal programma deve lanciare una SIGINT ai clienti ancora connessi..
il fatto è che se i clienti che si sono loggati lasciano il programma con una exit tramite i figli,il padre non saprà mai quale dei client connessi avvertire o meno,sto cercando una soluzione a questo dilemma qua...(idee?)
credevo che una variabile globale potesse risolvere,ma hai ragione è una cazzata perchè sono pur sempre due processi distinti e ognuno ha il suo stack...
grazie
ilsensine
20-09-2007, 20:03
Non è che si capisce molto quello che hai tirato su dalla tua descrizione...se può aiutarti, sappi che un child che termina causa l'invio al padre di un SIGCHLD che puoi intercettare. Dentro l'handler del segnale puoi eseguire una waitpid che ti ritorna il pid del child terminato.
trallallero
21-09-2007, 09:19
la struttura dati è globale,dichiarata fuori dal main,inizializzata appena dentro il main,a questa possono accedere anche i processi figli(ognuno tratta un cliente differente e si preoccupa di rimuovere il pid quando se ne va)
scusa ma mi sembra sporchissima come cosa.
Perche´ il client deve conoscere il proprio nome e i l proprio pid (il pid lo puo´ ottenere comunque con la getpid(), il nome glielo puoi passare come argomento) ?
E poi, come ti ha fatto notare ilsensine, se la variabile non la passi al processo (execvp etc) ti puoi scordare la visibilita´ delle variabili globali (che sono comunque sconsigliate).
santaclause83
21-09-2007, 09:46
la situazione è:
-cliente si logga
-server affida al cliente un processo figlio
-processo figlio comunica col cliente tramite pipe dedicata e serve le sue richieste
-tra queste c'è anche la richiesta di uscire dal programma("exit")..
il problema mio era che se il server principale viene chiuso malamente,deve gestire l'interruzione e avvertire i client ancora connessi della sua ahimè disdicevole dipartita
MA,se il client quando decide di andarsene con la "exit" avverte il processo figlio,il server non saprà mai chi avvertire sulla gestione di un ctrl-c improvviso,perchè a lui l'informazione della uscita del client non può arrivare tramite il figlio(e qui disperandomi e confondendomi ho fatto la cazzata della variabile globale descritta sopra..)
l'informazione non arriva AMMESSO CHE se io server quando faccio un figlio per trattare l'ennesimo cliente metto sia il pid del figlio(me lo restituisce la fork no?) sia il pid del cliente (che me lo spedisce quando si logga) in una struttura dati,quando il mio povero figlio muore nella gestione della SIGCHLD tramite il pid del figlio accedo alla struttura dati creata in partenza ed elimino sia il pid del figlio sia il pid del client (e ringrazio ilsensine che mi ha instradato nella soluzione)
DIMODOCHE',quando arriva un ctrl-c scorro la struttura dati e prima di morire definitivamente mando delle SIGINT ai pid client rimasti.
stavolta spero di essere stato chiaro,e se avete da appuntare appuntatelo
grazie ancora
ilsensine
21-09-2007, 10:07
la situazione è:
-cliente si logga
-server affida al cliente un processo figlio
-processo figlio comunica col cliente tramite pipe dedicata e serve le sue richieste
Forse puoi gestire più efficacemente la situazione tramite i thread.
nb comunque esiste un altro modo per inviare un segnale a tutti i (o determinati) child di un processo -- i process group:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void process()
{
signal(SIGUSR1, SIG_DFL);
while (1) {
fprintf(stderr, "Processo %d\n", getpid());
sleep(1);
}
_exit(0);
}
void createChild()
{
pid_t c = fork();
if (c==0)
process();
if (setpgid(c, getpid())<0)
perror("setpgid");
}
int main()
{
signal(SIGUSR1, SIG_IGN);
if (setpgrp()<0)
perror("setpgrp");
createChild();
createChild();
sleep(3);
killpg(getpid(), SIGUSR1);
fprintf(stderr, "Fatto.\n");
return 0;
}
santaclause83
21-09-2007, 10:56
ho tirato fuori una cosa del genere,arriva un SIGCHLD,entra in gioco questo gestore
nella struttura dati clienti sono presenti per ogni pointer nomecliente,pidcliente,pidfiglio
li trovo con la waitpid e li azzero
quando il server principale riceverà un ctrl-c scorrerà l'array e ucciderà tutti i pid nonzero che troverà sul suo cammino
se i processi diventano molti,riconosco che è un pò pesante e servirebbe un process group
void gestore2(int signal){
int status;
pid_t figlio;
figlio = wait(&status);
int conta = 0;
while(clienti[conta] != NULL){
if(clienti[conta]->pidson == figlio){
clienti[conta]->pid = 0;
clienti[conta]->pidson = 0;
}
conta++
}
}
potrebbe andare?
ilsensine
21-09-2007, 13:37
Non che miaccia molto come è scritto, ma dovrebbe.
Continuo a dire che dovrtesti usare i thread.
santaclause83
25-09-2007, 17:21
la wait della procedura di gestione del segnale SIGCHLD che ho riportato sopra adesso continua a resituirmi -1 al posto del pid del figlio appena uscito dal programma
se stampo su schermo errno è 10, cioè che "Il processo chiamante non ha nessun figlio inaspettato"
non capisco da cosa possa venir fuori una cosa del genere,soprattutto perchè in precedenza andava,l'unica cosa è che ho aggiunto un processo in più sopra che esce e lascia che il processo padre con i suoi figli girino in background...c sto impazzendo sopra!
:muro:
vBulletin® v3.6.4, Copyright ©2000-2026, Jelsoft Enterprises Ltd.