Newsgroup: it.comp.lang.c++
Titolo: eccezioni e threads

credo di essere ot perche' in threads non rientrano nello standard c++ (o mi
sbaglio?)
pero' il problema riguarda molte piattaforme e quindi ho deciso di postare
qui ugualmente, spero mi scuserete (e mi sarete anche di aiuto! ^___^;)
il problema e' questo: ho notato che se un thread lancia un'eccezione,
questa puo' essere intercettata da un catch nella funzione che ha creato il
thread. esempio:
... thread1 ()
{
    ...
    try
    {
         crea thread2();
    }
    catch (int x)
    ...
}
... thread2 ()
{
    ...
    throw int(2);
 ...
}
le funzioni thread1 e thread2 sono eseguite da thread diversi. se pero'
thread2 e' eseguita dal thread creato in thread1 (come nell'esempio) e
thread2 lancia un'eccezione, questa viene intercettata in thread1.
nb: non so quale thread finisce per eseguire codice nel catch di thread2 (ma
presumibilmente thread2)
questo e' un comportamento garantito dalle varie implementazioni dei thread
oppure e' un side-effect dell'implementazione delle gestioni del tutto
casuale e che varia da piattaforma a piattaforma (io ho verificato con vc e
lo faro' con gcc)
grazie & scusate
Touch


Lo standard dice:
[ When an exception is thrown, control is transferred to the nearest handler
with a matching type (15.3);
"nearest" means the handler for which the compoundstatement,
ctorinitializer, or functionbody
following the try keyword was most recently entered by the thread of control
and not yet exited. ]
Quindi il comportamento che denoti rientra nello standard.
-- 
Posted from 
nts-03.mm.eutelsat.org
 [194.214.173.15] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 Quindi il comportamento che denoti rientra nello standard.
Mi sa che la cosa è interpretabile. Il thread che lancia l''eccezione è
NATO dopo l'esecuzione della try. Quindi se il sistema implementa il
thread come una duplicazione del thread padre allora hai ragione.
Altrimenti no. Credo che un comportamento differente sarebbe altrettanto
standard.
Comunque trovo che per quanto mi riguarda se dovessi creare una
applicazione exception safe multithreaded metterei una catch(...) sia
nel main che nelle funzioni iniziali di tutti i thread. Ovvero mi
assicurerei che il caso specifico non si presenti mai.
--
Andrea Ferro
---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info 
http://www.brainbench.com/transcript.jsp?pid=2522556

 More info 
http://www.brainbench.com/transcript.jsp?pid%22556


 (ma presumibilmente thread2)
La cosa mi puzza....
Considera questo esempio:
try
{
        Oggetto obj;
        crea_thread ( f ); // f lancera' un eccezione
 
        fa_qualcosa( obj ); // questo potrebbe finire prima o dopo che 
                          // f lanci l'eccezione
}
catch(...)
{
}
Se "per assurdo" l'eccezione lanciata dal thread che esegue f()
venisse raccolta da questa catch, l'oggetto automatico obj verrebbe 
distrutto.
In particolare,
   se l'eccezione venisse lanciata mentre il thread principale e' ancora
   dentro il blocco try catch, si vedrebbe "sparire" obj.
   Se invece il thread principale fosse gia' uscito, obj verrebbe distrutto
   due volte.
Entrambi i casi sono impossibili. 
Quando viene creato un nuovo thread, questo avra' un suo "stack" dedicato
e indipendente dallo stack del thread che lo ha creato.
Quendo l'eccezione viene lanciata, lo stack viene "srotolato", in cerca
di una catch. Se lo stack "finisce" il programma dovrebbe uscire con
una uncaught exception.
Nel caso specifico dei thread non so se solo il thread viene terminato
e se anche il resto del programma (questo potrebbe dipendere 
dall'implementazione, dalla piattaforma etc.)
Sei proprio sicuro che l'eccezione viene lanciata dal thread figlio
e non dalla funzione del thread padre che si occupa di creare il figlio
e mandarlo in esecuzione ?
Fabio
-- 
Posted from 
flopiano.mm.eutelsat.org
 [194.214.173.28] 


 Provero' a fare degli esperimenti e vi faccio sapere.
Li ho fatti.
Quello che succede e' quello che tutti, non fuorviati dall' OP,
avremmo subito pensato:
La mia classe thread e' la seguente, e il metodo createThread
si occupa di creare un thread e lanciare il metodo Run()
all'interno del nuovo thread;
class Thread {
    void run() {  
        Sleep(2000); 
        if (excp) throw 3;
        while (1) 
            if (!running) 
                break;
    }
public:
    Thread(bool excp) 
    :running(false), excp(excp) {}
    void createThread() { 
            running  =   true; 
            /* altre operazioni */ 
            run();
    }
    void stop() { running   =    false; }
 
private:
    bool running;
    bool excp;
};
========= Prova 1============
Thread pThread = new Thread(false); //non tira eccezioni 
try {
    pThread->createThread();
}
catch(...) {
    std::cout << "catch(...)" << std::endl;
}
pThread->stop();
===========================
e' andato tutto bene.
========= Prova 2============
Thread pThread = new Thread(true); //tira un'eccezione dopo 2 sec
try {
    pThread->createThread();
}
catch(...) {
    std::cout << "catch(...)" << std::endl;
}
Sleep(4000);    
pThread->stop();
===========================
Qui si e' piantato il programma infatti il thread ha tirato 
un'eccezione mentre il main era fermo sulla sleep esterna
alla catch, si potrebbe pensare che se la sleep fosse dentro ci
salveremmo ma la seguente prova ci smentisce:
========= Prova 3============
Thread pThread = new Thread(true); //tira eccezioni dopo 2 sec
try {
    pThread->createThread();
    Sleep(4000);    
}
catch(...) {
    std::cout << "catch(...)" << std::endl;
}
pThread->stop();
===========================
si e' pianto ugualmente nonostante il main
fosse fermo ancora dentro la try.
Come avevo detto prima il nuovo thread ha un suo stack e quando 
tira un'eccezione e quello che stack che viene
srotolato alla ricerca di una catch non lo stack del padre.
Ciao
Gaetano.


 avremmo subito pensato:
Tutto questo ovviamente col tuo specifico compilatore, sulla tua
specifica piattaforma, che supporta uno specifico modello di threading.
Qualunque altra piattaforma e' libera di comportarsi come gli pare, dal
momento che il multithreading non e' contemplato dallo standard.
Ciao,
Nicola


Ovviamente. Pero' io parlerei al plurale:
Con i miei specifici compilatori, sulle mie specifiche piattaforme.


 Con i miei specifici compilatori, sulle mie specifiche piattaforme.
Sembri Scott Meyers :-)
Ciao,
Nicola

 Sembri Scott Meyers :-)
Sul serio?   :-(  
PS. Sta veramente scadendo quell'uomo!!!


 Considera questo esempio:
[snip]
interessante e significativo
comunque, vale quanto ha detto Nicola e cioe' che non essendo contemplato
dallo standard...
vi ringrazio per l'attenzione, e per quanto mi riguarda ho dedotto che
mettero' un bel catch(...) ad ogni thread
(non so cosa mi fosse preso di voler utilizzare le eccezioni come meccanismo
di comunicazione fra thread... la cosa e' veramente patologica!!)
bye
Touch

 PS. Sta veramente scadendo quell'uomo!!!
dato che non ci sono di faccine immagino che non sia una battuta. Cosa 
intendi di preciso?
ciao Anto
-- 
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

 intendi di preciso?
L'ultimo libro che ha scritto Effective STL se lo poteva risparmiare
o almeno maturarlo un po di piu, per non parlare che se io inizio
a sembrare lui  :-)
