Vytvořím vedlejší thread pomocí modulu threading a dám mu za úkol čekat. Spustím ho, a v hlavním threadu dám pořád dokola něco vypisovat. Když potom ale dám KeyboardInterrupt, tak se hlavní thread ukončí, ale vedlejší zůstane viset na tom čekání. Je nějakej způsob, jak thread ukončit i s tím čekáním?
Jak zabít thread netuším, ostatně soudím, že by si to měl thread hlídat sám a ukončit se po požádání jiným threadem.
Pokud stačí, aby po skončení hlavního threadu skončil celý proces, hledej klíčové slovo daemonic v modulu threading. Threadu tím můžeš nastavit příznak, že proces na něj nemá při ukončení čekat.
> Vytvořím vedlejší thread pomocí modulu threading a dám mu za úkol čekat. > Spustím ho, a v hlavním threadu dám pořád dokola něco vypisovat. Když potom > ale dám KeyboardInterrupt, tak se hlavní thread ukončí, ale vedlejší zůstane > viset na tom čekání. Je nějakej způsob, jak thread ukončit i s tím čekáním?
Odstřelení threadu se obecně lidi brání, protože to je dost drastická věc, která mimo jiné může uvést i Váš program do neschopnosti dál pokračovat. Uvědomte si, že každý thread má svůj zásobník, a při násilném odstřelení threadu operační systém většinou zásobník neuklízí, ale nechá ho jakožto blok paměti v adresovém prostoru procesu být a nikdy ho neuvolní. Je to proto, že na zásobníku mohou být proměnné a data, které používají jiné thready, a pokud thread odstřelíte násilně, operační systém se domnívá, že je to nouzová akce, a že ostatní thready netuší o tom nic. A proto jim nechá zásobník s daty k dispozici, pokud by je náhodou jiné thready používaly.
Zatímco při slušném způsoby ukončení, kdy se thread sám ukončí, operační systém po něm uklidí vše i zásobník.
V praktickém programu pak zejména ve 32 bitovém systému máte omezený adresový prostor obvykle kolem 2 GB, a po určitém poměrně malém počtu takto násilně odstřelených threadu (kolem tisícovky) zaplníte celý adresový prostor procesu neuklizenými zásobníky, které nemáte jak uvolnit a můžete se dostat do stavu, kdy prostě program nebude schopen pokračovat v běhu, neboť nebude mít kam namapovat paměť.
Proto se thready opravdy násilně neodstřelují, ale pouze se threadu nastaví příznak "hele threade, ukonči se prosím". A běžící thread příznak dostatečně často čte, řekněme třeba stokrát za sekundu, a jakmile zjistí, že by se měl ukončit, tak prostě se sám ukončí, čím se předejde výžše uvedenému zlu.
> Vytvořím vedlejší thread pomocí modulu threading a dám mu za úkol čekat. > Spustím ho, a v hlavním threadu dám pořád dokola něco vypisovat. Když potom > ale dám KeyboardInterrupt, tak se hlavní thread ukončí, ale vedlejší zůstane > viset na tom čekání. Je nějakej způsob, jak thread ukončit i s tím čekáním?
> Vytvořím vedlejší thread pomocí modulu threading a dám mu za úkol čekat. > Spustím ho, a v hlavním threadu dám pořád dokola něco vypisovat. Když potom > ale dám KeyboardInterrupt, tak se hlavní thread ukončí, ale vedlejší zůstane > viset na tom čekání. Je nějakej způsob, jak thread ukončit i s tím čekáním?
Moc tomu nerozumím, takže se omlouvám, jestli budu plácat nesmysly; Není to bezpečnostní chyba? Pokud si něco vezme paměť a OS jí po sestřelení neuvolní, zdá se mi to jako potenciální riziko, které by mohlo být zneužito nějakým škodlivým virem..
> ------------ Původní zpráva ------------ > Od: superman <f...@centrum.cz> > Předmět: Re: [python] Ukončení zaneprázdněného threadu > Datum: 24.4.2008 21:43:38 > ---------------------------------------- > Odstřelení threadu se obecně lidi brání, protože to je dost drastická > věc, která mimo jiné může uvést i Váš program do neschopnosti dál > pokračovat. Uvědomte si, že každý thread má svůj zásobník, a při > násilném odstřelení threadu operační systém většinou zásobník neuklízí, > ale nechá ho jakožto blok paměti v adresovém prostoru procesu být a > nikdy ho neuvolní. Je to proto, že na zásobníku mohou být proměnné a > data, které používají jiné thready, a pokud thread odstřelíte násilně, > operační systém se domnívá, že je to nouzová akce, a že ostatní thready > netuší o tom nic. A proto jim nechá zásobník s daty k dispozici, pokud > by je náhodou jiné thready používaly.
> Zatímco při slušném způsoby ukončení, kdy se thread sám ukončí, operační > systém po něm uklidí vše i zásobník.
> V praktickém programu pak zejména ve 32 bitovém systému máte omezený > adresový prostor obvykle kolem 2 GB, a po určitém poměrně malém počtu > takto násilně odstřelených threadu (kolem tisícovky) zaplníte celý > adresový prostor procesu neuklizenými zásobníky, které nemáte jak > uvolnit a můžete se dostat do stavu, kdy prostě program nebude schopen > pokračovat v běhu, neboť nebude mít kam namapovat paměť.
> Proto se thready opravdy násilně neodstřelují, ale pouze se threadu > nastaví příznak "hele threade, ukonči se prosím". A běžící thread > příznak dostatečně často čte, řekněme třeba stokrát za sekundu, a > jakmile zjistí, že by se měl ukončit, tak prostě se sám ukončí, čím se > předejde výžše uvedenému zlu.
> Miloslav Ponkrác
> Jakub Lužný napsal(a): > > Zdarec :-)
> > Vytvořím vedlejší thread pomocí modulu threading a dám mu za úkol čekat. > > Spustím ho, a v hlavním threadu dám pořád dokola něco vypisovat. Když potom > > ale dám KeyboardInterrupt, tak se hlavní thread ukončí, ale vedlejší zůstane > > viset na tom čekání. Je nějakej způsob, jak thread ukončit i s tím čekáním?
Proč by to mělo být bezpečnostní riziko? Je na Vás, jakožto tvůrci programu, zda vůbec dovolíte externímu programu sestřelit thread, nebo ne. Uvědomte si, že existují něco jako přístupová práva v každém operačním systému, a není nutné dovolit sestřelení threadu nikým jiným, než si sám přejete. A kromě toho se tu bavíme o sestřelení threadu jiným threadem v rámci jednoho procesu.
Neuvolněná paměť v rámci procesu je něco co vzniká naprosto běžně. Staší neuvolnit kus paměti. Pokud k paměti nepřistupujete, systém jí brzy odswapuje na disk a z fyzické paměti RAM neubírá. Akorát ubírá místo v adresovém prostoru procesu (a nikde jinde). Po skončení procesu samozřejmě systém uklidí naprosto vše.
Ale je to bezpečnostní chyba, nebo raději řekněme problém pro programy co se neumějí vypořádat s nedostatkem paměti - ale je to chyba samotného programu. Problém mívají obecně jazyky jako typu Python, Java, C#, Perl, a další, které prostě neumí nedostatek paměti nijak rozumně vyřešit, a v zásadě pouze krachnou. V jazycích jako je asm, C, C++, Ada, Fortran, a další je možné bez problémů situaci, kdy dojde paměť, nebo adresovatelný prostor procesu zvládnout a pokračovat v běhu - ba se dokonce zotavit a bezpečně jet. Ovšem programátor ten program tak musí napsat.
Nedávno jsem takto prolomil "neprůstřelný" firewall Kerio Personal Firewall. Stačilo k tomu zabrat veškerou paměť a počkat několik sekund. Uvnitř Kerio firewallu psaném v C++ došlo k pokusu o alokaci bloku paměti při další síťovém spojení - alokace se nezdařila, vyhodila vnitřní výjimku typu bad_alloc, kterou programátoři Keria neošetřili a celý firewall jako program se ukončil, spadl na ústa a připojení k internetu najednou byla zcela nachráněné. Jak jednoduché, jak účinné. Už vím, jak bych napsal virus, který se dostane na síť při puštěném Kerio firewallu (pro objektivitu musím napsat, že by to nejspíš neustála naprostá většina firewallů.).
> Moc tomu nerozumím, takže se omlouvám, jestli budu plácat nesmysly; > Není to bezpečnostní chyba? Pokud si něco vezme paměť a OS jí po sestřelení neuvolní, zdá se mi to jako potenciální riziko, které by mohlo být zneužito nějakým škodlivým virem..