Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Star Wars Zero Company è l'erede di XCOM 2
Star Wars Zero Company è l'erede di XCOM 2
Bit Reactor porta nell’universo di Star Wars una struttura tattica che richiama apertamente XCOM 2, ma la arricchisce con legami tra i personaggi, progressione ruolistica, gestione della base e un sistema di combattimento costruito attorno a tre Punti Azione e alle risorse condivise della squadra
Test ride Can-Am Origin: la moto elettrica che fa dimenticare il motore a scoppio (ma occhio all'autonomia)
Test ride Can-Am Origin: la moto elettrica che fa dimenticare il motore a scoppio (ma occhio all'autonomia)
Abbiamo provato per una settimana intera la Can-Am Origin, la Dual Sport elettrica del gruppo canadese BRP: ecco com'è andata tra città, autostrada e un primo assaggio di sterrato
Logitech G325, G305 e G316 X: il tris per chi non vuole rinunciare a nulla, spendendo poco
Logitech G325, G305 e G316 X: il tris per chi non vuole rinunciare a nulla, spendendo poco
Nelle ultime settimane abbiamo provato il mouse Logitech G305, la tastiera G316 X 98 e le cuffie G325. Si tratta del setup entry-level di Logitech che ormai, di "entry-level" ha ben poco. Tastiera e mouse offrono prestazioni di livello competitivo con quasi nessuna rinuncia e un livello di personalizzazione estremamente elevato. Le cuffie, invece, hanno mostrato qualche debolezza, ma propongono un ventaglio di funzionalità completo che consente di abbandonare completamente i cavi
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 12-07-2011, 09:24   #1
agosteeno
Member
 
Iscritto dal: Aug 2009
Messaggi: 119
[C] [risolto] terminazione pulita di un server multithread

Salve a tutti ho una questione da sottoporvi, per avere qualche consiglio. Per un esame ho un server multithread. La terminazione dell'esecuzione deve avvenire tramite il trattamento del segnale SIGINT e SIGTERM. Il problema nasce dal fatto che quando si chiede di terminare l'esecuzione, si devono terminare tutte le operazioni in coda richieste dai vari client (per ognuno dei quali c'e' un thread apposito che lo serve) piu' un thread particolare che si attiva ogni tot secondi e serve tutte le richieste in coda. Quando arriva una di questi segnali questo thread dovrebbe iniziare la sua esecuzione, soddisfare le ultime richieste in coda e poi chiudere il server in maniera pulita (quindi chiudere la socket, chiudere file aperti e cose del genere). Questo thread a regime esegue un ciclo infinito e una sleep di tot secondi per regolare la temporizzazione. Il trattamento dei segnali e' gestito installando dei gestori, tramite una funzione particolare. Come potrei sistemare il gestore di SIGINT e SIGTERM per fare in modo che il thread si renda conto che nn ha semplicemente eseguito una sleep e quindi possa terminare il ciclo infinito e terminare il server?

Ultima modifica di agosteeno : 02-09-2011 alle 10:50. Motivo: problema risolto
agosteeno è offline   Rispondi citando il messaggio o parte di esso
Old 12-07-2011, 10:46   #2
WarDuck
Senior Member
 
L'Avatar di WarDuck
 
Iscritto dal: May 2001
Messaggi: 13045
Cosa fai di preciso all'interno del ciclo in cui è inserita la sleep?

Potresti pensare di impostare opportunamente una variabile globale all'arrivo del segnale in questione, ad esempio un booleano.

Codice:
..

bool Run = TRUE;

while ( Run )
{
    // codice con sleep
}

/* Cleanup */
..
All'arrivo del segnale specificato Run viene posta a FALSE, così al successivo ciclo utile il while termina e puoi eseguire la cleanup.
WarDuck è offline   Rispondi citando il messaggio o parte di esso
Old 12-07-2011, 10:57   #3
agosteeno
Member
 
Iscritto dal: Aug 2009
Messaggi: 119
Grazie per la risposta. Allora, nel codice della sleep il thread esegue sostanzialemente le operazioni chieste dal client. Nel mio caso particolare si tratta di un server che gestisce richieste e offerte di carsharing. Il problema pero' nn e' solo questo. Mi spiego meglio: il thread in questione ha un ciclo infinito e avevo gia' pensato si risolverlo in una maniera simile a come hai suggerito. Il fatto e' che anche il main esegue un ciclo infinito nel quale esegue una accept per accettare nuovi client e dunque dovrei terminare anche il suo ciclo. La variabile potrebbe essere globale nel senso che potrei usarla sia sul ciclo del main che del thread particolare? La cleanup la farebbe direttamente il thread che esegue le operazioni in modo tale da essere sicuro da soddisfare tutte le richieste pendenti...
agosteeno è offline   Rispondi citando il messaggio o parte di esso
Old 12-07-2011, 11:04   #4
agosteeno
Member
 
Iscritto dal: Aug 2009
Messaggi: 119
Tra l'altro ripensandoci potrei, invece di chiamare la pthread_detach appena creo il thread particolare, chiamare dal main la pthread_join quando esco dal ciclo, in modo da poter garantire la corretta terminazione. Infatti se nn sbaglio all'uscita del main dovrebbe terminare tutto il processo.
agosteeno è offline   Rispondi citando il messaggio o parte di esso
Old 12-07-2011, 11:22   #5
agosteeno
Member
 
Iscritto dal: Aug 2009
Messaggi: 119
Piccolo problema: per il main nn posso usare questa soluzione perche' in realta' lui e' bloccato sulla accept. Di conseguenza dovrebbe per lo meno accettare una nuova richiesta e poi all'iterazione successiva, quando ricontrolla la variabile uscirebbe dal ciclo. Ma questo non e' il comportamento che voglio. Senza contare il fatto che questa richiesta potrebbe nn arrivare mai e dunque il server non terminare...
agosteeno è offline   Rispondi citando il messaggio o parte di esso
Old 12-07-2011, 12:33   #6
WarDuck
Senior Member
 
L'Avatar di WarDuck
 
Iscritto dal: May 2001
Messaggi: 13045
Relativamente alla accept

Se non ricordo male alla ricezione dei segnali alcune chiamate a funzione possono terminare.

Per evitare ciò ci sono due modi, uno è mascherare i segnali, mentre l'altro è semplicemente riavviare la funzione (credo ci sia un flag da passare da qualche parte).

Ora non ricordo esattamente i dettagli di questa cosa, però potresti sfruttare questo comportamento per la accept (che a quel punto terminerebbe e dunque il ciclo verrebbe sbloccato).

Una alternativa a questa cosa potrebbe essere effettuare una connessione locale al server e mandare un messaggio preciso di chiusura.

Edit

Ho trovato:

http://linux.die.net/man/2/sigaction

Mi ricordavo bene, il flag SA_RESTART ti consente di far ripartire la funzione.

Se tu prepari un handler separato per i segnali che ti interessano e chiami questa funzione senza passargli il flag SA_RESTART, alla ricezione dei segnali le chiamate in attesa dovrebbero terminare.

Ultima modifica di WarDuck : 12-07-2011 alle 12:43.
WarDuck è offline   Rispondi citando il messaggio o parte di esso
Old 12-07-2011, 13:34   #7
agosteeno
Member
 
Iscritto dal: Aug 2009
Messaggi: 119
Devo giusto precisare che si tratta di un client server gia' locale. Locale nel senso che le socket usate sono le AF_UNIX. Si tratta di un progetto per il laboratorio di sistemi operativi. Non ho ben capito come dovrebbe funzionare il flag sa_restart: in pratica con un handler nel quale modifico una variabile (in questo caso particolare) basterebbe a risolvere la situazione perche' le chiamate che sono in attesa verrebbero sbloccate?
agosteeno è offline   Rispondi citando il messaggio o parte di esso
Old 12-07-2011, 16:55   #8
WarDuck
Senior Member
 
L'Avatar di WarDuck
 
Iscritto dal: May 2001
Messaggi: 13045
Quote:
Originariamente inviato da agosteeno Guarda i messaggi
Devo giusto precisare che si tratta di un client server gia' locale. Locale nel senso che le socket usate sono le AF_UNIX. Si tratta di un progetto per il laboratorio di sistemi operativi. Non ho ben capito come dovrebbe funzionare il flag sa_restart: in pratica con un handler nel quale modifico una variabile (in questo caso particolare) basterebbe a risolvere la situazione perche' le chiamate che sono in attesa verrebbero sbloccate?
Di default alla ricezione di un segnale alcune chiamate di sistema vengono interrotte (dunque falliscono e riportano codice di errore EINT), quel flag serve per farle ripartire.

In genere può essere comodo farle ripartire quando devi gestire segnali custom tipo SIGUSR1 e SIGUSR2.

Nel tuo caso però vuoi avere il comportamento di default, con le funzioni che vengono interrotte alla ricezione di un segnale.

Ultima modifica di WarDuck : 12-07-2011 alle 16:59.
WarDuck è offline   Rispondi citando il messaggio o parte di esso
Old 12-07-2011, 17:00   #9
agosteeno
Member
 
Iscritto dal: Aug 2009
Messaggi: 119
Lavorandoci su mi sono reso conto che sostanzialmente interrompe la funzione. Quindi ho fatto cosi': controllo il valore restituito. Se = -1 allora significa che la accept e' stata interrotta bruscamente. Faccio un break ed esco dal ciclo. A questo punto controllo il valore della variabile globale (ho visto che devo definirla di tipo volatile sig_atomic_t): se ha il valore dato dal gestore (che poi e' anche quello che serve per far terminare il while del thread che esegue le altre operazioni) allora significa che si tratta di una terminazione gentile. Quindi faccio la join su questo thread e lui eseguira' la pulizia. Altrimenti si tratta di una situazione anomala e vedro' di trattarla di conseguenza. Per ora sembra andare bene, per lo mena pare faccia quello che voglio io.
agosteeno è offline   Rispondi citando il messaggio o parte di esso
Old 13-07-2011, 08:53   #10
WarDuck
Senior Member
 
L'Avatar di WarDuck
 
Iscritto dal: May 2001
Messaggi: 13045
Quote:
Originariamente inviato da agosteeno Guarda i messaggi
Lavorandoci su mi sono reso conto che sostanzialmente interrompe la funzione. Quindi ho fatto cosi': controllo il valore restituito. Se = -1 allora significa che la accept e' stata interrotta bruscamente. Faccio un break ed esco dal ciclo. A questo punto controllo il valore della variabile globale (ho visto che devo definirla di tipo volatile sig_atomic_t): se ha il valore dato dal gestore (che poi e' anche quello che serve per far terminare il while del thread che esegue le altre operazioni) allora significa che si tratta di una terminazione gentile. Quindi faccio la join su questo thread e lui eseguira' la pulizia. Altrimenti si tratta di una situazione anomala e vedro' di trattarla di conseguenza. Per ora sembra andare bene, per lo mena pare faccia quello che voglio io.
Senza usare break:

Codice:
while ( accept(..) >= 0 )
{
   ...
}

/* Codice di cleanup */
Relativamente al cleanup, immagino che ogni thread abbia il suo insieme di risorse da liberare, come la gestisci questa cosa?

Riguardo alle variabili globali bisogna vedere quanti thread vogliono accedere a quella variabile e come questa variabile viene modificata dal gestore del segnale.

Se la catena degli eventi è strettamente:
- ricezione segnale
- gestione tramite sighandler
- terminazione accept

Allora non dovresti aver bisogno di accorgimenti particolari, perché quando termina accept sei sicuro che Run è cambiata e vi accedi quando nessun'altro più può cambiarla (per stare sicuro puoi mascherare a quel punto l'arrivo di nuovi segnali, anche se non dovrebbe essere necessario).

.

Ultima modifica di WarDuck : 13-07-2011 alle 08:55.
WarDuck è offline   Rispondi citando il messaggio o parte di esso
Old 13-07-2011, 09:15   #11
agosteeno
Member
 
Iscritto dal: Aug 2009
Messaggi: 119
Grazie per il consiglio sul break, tanto semplice ma nella fretta nn mi e' venuto in mente! Riguardo alla variabile globale verra' usata solo da 2 diversi thread in lettura e in scrittura solo dall'handler, quindi nn dovrebbe dare problemi. Per quanto riguarda le risorse che devono liberare gli altri thread ancora nn ho ben deciso anche perche' a parte il fatto di avere una connessione attiva con i client (che nn e' un dettaglio da poco) devono effettuare solo le eventuali free del caso. Anche gli altri thread cmq hanno un ciclo al loro interno, all'interno del quale ascoltano le varie richieste dei client. Usero' anche per loro un meccanismo simile a quello detto fin'ora, considerando il fatto che in realta' le risposte ai client le invia il thread di cui parlavo nei post precedenti.
agosteeno è offline   Rispondi citando il messaggio o parte di esso
Old 31-08-2011, 11:29   #12
agosteeno
Member
 
Iscritto dal: Aug 2009
Messaggi: 119
Salve, riprendo questa discussione perche' si tratta sempre della stessa problematica.

La situazione attuale e' questa: quando effettuo un ctrl-c il server deve terminare gentilmente e questo verra' fatto da un thread che di base effettua un altro compito, ma al suo interno ha un ciclo, la cui condizione viene cambiata dal gestore del SIGINT per fare in modo che quando viene gestito esca dal ciclo ed effettui le operazioni del caso. Il main e' bloccato sulla accept perche' il suo compito e accettare nuove connessioni da parte di client (la accept e' anche la condizione del while: while ((canale = accept(socket)) >= 0)). All'uscita di questo while c'e' l'attesa per la terminazione del thread di prima (pthread_join) piu' altre operazioni del caso.
In teoria, quando il server riceve il SIGINT, siccome il main era bloccato in attesa sulla accept (in realta' si tratta di una mia funzioncina che chiama la accept, ma e' sostanzialmente identica ad una accept normale) dovrebbe sbloccarsi, restituire -1 aggiornando il valore di errno a EINTR e dunque causare l'uscita dal ciclo. Questo pero' non avviene e non riesco a capire per quale motivo. In pratica rimane bloccato (nel senso che la accept non restituisce nessun valore) ma non accetta neanche nuove connessioni e dunque e' chiaro che la ricezione del segnale ha avuto un qualche effetto.
Per la gestione dei segnali ho un file particolare che implementa una funzione che carica i gestori dei segnali interessati, tra cui il SIGINT e nn mi sembra ci siano maschere attive o flag settati.
Qualcuno ha idea di quale possa essere il problema?
agosteeno è offline   Rispondi citando il messaggio o parte di esso
Old 02-09-2011, 10:49   #13
agosteeno
Member
 
Iscritto dal: Aug 2009
Messaggi: 119
Ok, problema risolto! Il problema era un cattivo uso delle maschere per i segnali. Oltretutto nella funzione che installa i gestori mi dimenticavo di disabilitare la maschera. Almento il tutto mi e' servito per capire bene come funziona i segnali! Grazie a tutti
agosteeno è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Star Wars Zero Company è l'erede di XCOM 2 Star Wars Zero Company è l'erede di XCOM ...
Test ride Can-Am Origin: la moto elettrica che fa dimenticare il motore a scoppio (ma occhio all'autonomia) Test ride Can-Am Origin: la moto elettrica che f...
Logitech G325, G305 e G316 X: il tris per chi non vuole rinunciare a nulla, spendendo poco Logitech G325, G305 e G316 X: il tris per chi no...
Recensione POCO F9 pro: potenza da vero top di gamma, display da 185 Hz e finalmente una fotocamera da prendere sul serio Recensione POCO F9 pro: potenza da vero top di g...
Tra audio e AI: la ricetta di Qualcomm per l'agentic AI Tra audio e AI: la ricetta di Qualcomm per l'age...
Google perde la testa: AI Overview conso...
Anthropic presenta Claude Sonnet 5.5, e ...
ESA e ClearSpace svilupperanno un satell...
Oracle, stock option da quasi un miliard...
Starship: si è conclusa anticipat...
Un computer quantistico ha funzionato ne...
Sovranità sui dati: AWS è ...
Il nuovo nome della distro Linux mobile ...
Due ventole da 220 mm e non solo: Cooler...
Truffa telefonica via Google Ads: il bro...
Google pensiona le Gems di Gemini: cosa ...
Flight 14: incertezza per un problema a ...
C'è un problema con i robot Tesla: i dip...
Raggi gamma anomali dalla Via Lattea sve...
NIO vende il 30% della divisione scambio...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 22:33.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v