Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



Výjimky a thready

Seznam témat     Nová odpověď

Přihlásit se     Registrace     Zapomenuté heslo

Re: Výjimky a thready

Autor: AnonymousUser

14:25:51 12.08.2010

...Resp. - co myslíte "přenést výjimku", když jsme se již shodli, že "throw/catch" se dá udělat pouze v rámci téhož threadu? Chápete "přenést výjimku" jako "přenést informaci o vzniklé výjimce"?

Vyhozená výjimka musí být vždy ošetřena ve stejném threadu. To je absolutní pravidlo. Tedy implementační detail. Přímo catch ani nic jiného neumí.

Ovšem co si nad toutou implementací postavíte jako abstrakci je Vaše věc. Ovšem někde uvnitř toho všeho musí dojít k tomu, že původní thread výjimku nějak zpracuje – ne nutně pomocí catch, ale ta výjimka musí být ošetřena.

Stejně tak třeba píšete, že C/C++ umí psát do souboru. Neumí. C/C++ Vám do souboru nezapíše ani ň. Jen postavilo abstrakci, knihovní funkce, které někde uvnitř implementace úlohu zápisu do souboru přenesou mimo C/C++ program na volání operační systému, který to skutečně udělá.

Takže někde uvnitř musí vždy dojít k tomu, že výjimka je ošetřena v tom threadu, kde byla vyhozena. Tomu se nedá vyhnout. Nějak, jakkoli. Ale můžete si nad tím postavit lecjakou konstrukci, či abstrakci, která způsobí, že vy jako programátor už to nikdy řešit nebudete.

Miloslav Ponkrác

Citovat příspěvek

 

Re: Výjimky a thready

Autor: JiriValerian

10:06:24 12.08.2010

[color=#008000]Neon Napsal:
-------------------------------------------------------
> 2JV: Jestli jsem zvolil nevhodné fórum, tak se
> omlouvám. Nevím, jestli téma "hození výjimky v
> jednom threadu a chycení v jiném" je záležitostí
> specifikace jazyka C++ (=> diskuse cpp nebo
> paa) nebo konkrétního OS (=> tato diskuse). Tak
> jako tak, zajímá mě implementace pouze pod
> Windows, čili i příp. řešení použitelné pouze pod Win.[/color]

Pokud je řešení použitelné jak pod Windows tak i v jiných OS, pak by Vám nemělo vadit jej využít a řešení použitelné ve Windows a přesto nezávislé na Windows existuje a i když odkaz na něj patří spíš do již zmíněné konfery C++ tak ho sem výjimečně dávám. ;)

[b]Boost Exception: Transporting of Exceptions Between Threads[/b]
http://www.boost.org/doc/libs/1_39_0/libs/exception/doc/tutorial_exception_ptr.html

Citovat příspěvek

 

Re: Výjimky a thready

Autor: Neon

9:48:22 12.08.2010

2JV: Jestli jsem zvolil nevhodné fórum, tak se omlouvám. Nevím, jestli téma "hození výjimky v jednom threadu a chycení v jiném" je záležitostí specifikace jazyka C++ (=> diskuse cpp nebo paa) nebo konkrétního OS (=> tato diskuse). Tak jako tak, zajímá mě implementace pouze pod Windows, čili i příp. řešení použitelné pouze pod Win.

2MP: Píšete:

"... Výjimku tak jako tak musí nějak odchytit thread, který jí vyhodil..."

OK, chápu, beru. Dále:

"... Pokud si nejste jistý v kramflecích, nepřenášejte výjimky mimo thread. Přeneste informaci jiným způsobem. ..."

Řekl bych, že (nyní) výjimku mimo thread nepřenáším (= ve smyslu thr2:throw + thr1:catch).

Resp. - co myslíte "přenést výjimku", když jsme se již shodli, že "throw/catch" se dá udělat pouze v rámci téhož threadu? Chápete "přenést výjimku" jako "přenést informaci o vzniklé výjimce"?

Výjimku teď chytám ve stejném threadu (= thr2), jako ji hodím. Jen po chycení signalizuji událost a pak čekám, až hlavní thread (= thr1) (který mj. tuto událost očekává) signalizuje, že ji zpracoval. Pak thr2 pokračuje. Tj. takto "přenáším informaci o vzniklé výjimce" mezi thready, nikoli výjimku jako takovou.

Ještě:

"... Já v projektech mezi thready C++ výjimky běžně přenáším. ..."

Máte tedy i zde na mysli "přenos informace o vzniklé výjimce"? Pokud ano, tak zřejmě nejsme v rozporu.

Jakým způsobem konkrétně tedy "přenášíte informaci o vzniklé výjimce"? Rovněž kombinací údálostí s předáním informace přes nějakou(é) porměnnou(é)?

Neon

Citovat příspěvek

 

Re: Výjimky a thready

Autor: AnonymousUser

9:26:11 12.08.2010

Kolem multithreadových věcí je nějaký jednoduchý popis dost nemožný.

Jinak multithreadové programování je něco jiného, než single thread. Rozhodně vymyslíte daleko více, než 2-3 použitelné metody. Klidně tisíc naprosto dobře použitelných metod.

Já v projektech mezi thready C++ výjimky běžně přenáším. Je to daleko luxusnější, když na výjimkách funguje to co má.

U všech multithreadových programů je na prvním místě návrh struktury programu, plánování threadů a synchronizace mezi nimi. Pokud tohle neuděláte a začnete aplikaci psát, (a nejedná se o triviální aplikaci) tak v lepším případě začnete synchronizaci různě lepit, v horším začne datová nekonzistence, nebo výkonnostní problémy.

I u těch výjimek mezi thready musí jiný thread vědět, že výjimka pochází odjinud. Nemůžete s výjimkou do programu vpadnout kdykoli, ale ve vhodný okamžik a ve vhodném kontextu.

Můžete si vybrat řešení neportabilní, kdy se přizpůsobíte kompilátoru a pak může být přenos výjimky takřka dokonalý a zcela automatický. Nebo portabilní, kde uděláte o řádek více.

Stejně tak je mnoho a mnoho aspektů.

Nejlepší řešení neexistuje, ve všech multithreadových aplikacích závisí nejlepšíá řešení na architektuře. Stejně tak jako není nejlepší synchronizační objekt (například spin lock je geniální do kernelu, ale nikoli do většiny programů, synchronizační sekce je velmi efektivní ve strojáku, mutex zase potřebuje daleko více, možné tisíce instrukcí + přepnutí kontextu mezi programem a kernelem, kromě toho třeba událost se hodí na něco jiného, než třeba mutex, atd.), a proto jich Windows obsahuje hned několik, tak neexistuje nejlepší metoda přenosu výjimky.

Pokud si nejste jistý v kramflecích, nepřenášejte výjimky mimo thread. Přeneste informaci jiným způsobem. Výjimku tak jako tak musí nějak odchytit thread, který jí vyhodil, jinak dojde k propagaci výjimky do hlavního rámce threadu a k předčasnému ukončení programu, nebo vyvolání funkce, viz příspěvek pana Valeriana.

Citovat příspěvek

 

Re: Výjimky a thready

Autor: JiriValerian

9:13:36 12.08.2010

Jsme v diskusi věnované Windows tedy předpokládám dotazy k obsluze výjimek na úrovni OS Windows viz SEH. Pro výjimky C++ nezávislé na OS je jiná diskuze viz odkaz http://forum.builder.cz/list.php?123

Zde je příklad k obsluze SEH ve Windows.

[size=14px][code][color=#0000FF]#include[/color] [color=#800080][/color]

LPSTR TypVyjimky [color=#800000]([/color]DWORD ExceptCode[color=#800000])[/color]
[color=#800000]{[/color]
[color=#0000FF]char[/color] [color=#800000]*[/color]Ret [color=#800000]=[/color] [color=#800080]"Neznámý"[/color][color=#800000];[/color]
[color=#008000]// viz http://msdn.microsoft.com/en-us/library/aa363082(v=VS.85).aspx[/color]
[color=#0000FF]switch[/color] [color=#800000]([/color]ExceptCode[color=#800000])[/color] [color=#800000]{[/color]
[color=#0000FF]case[/color] EXCEPTION_ACCESS_VIOLATION[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"ACCESS_VIOLATION"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_ARRAY_BOUNDS_EXCEEDED[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"ARRAY_BOUNDS_EXCEEDED"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_BREAKPOINT[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"BREAKPOINT"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_DATATYPE_MISALIGNMENT[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"DATATYPE_MISALIGNMENT"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_FLT_DENORMAL_OPERAND[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"FLT_DENORMAL_OPERAND"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_FLT_DIVIDE_BY_ZERO[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"FLT_DIVIDE_BY_ZERO"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_FLT_INEXACT_RESULT[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"FLT_INEXACT_RESULT"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_FLT_INVALID_OPERATION[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"FLT_INVALID_OPERATION"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_FLT_OVERFLOW[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"FLT_OVERFLOW"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_FLT_STACK_CHECK[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"FLT_STACK_CHECK"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_FLT_UNDERFLOW[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"FLT_UNDERFLOW"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_ILLEGAL_INSTRUCTION[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"ILLEGAL_INSTRUCTION"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_IN_PAGE_ERROR[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"IN_PAGE_ERROR"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_INT_DIVIDE_BY_ZERO[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"INT_DIVIDE_BY_ZERO"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_INT_OVERFLOW[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"INT_OVERFLOW"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_INVALID_DISPOSITION[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"INVALID_DISPOSITION"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_NONCONTINUABLE_EXCEPTION[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"NONCONTINUABLE_EXCEPTION"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_PRIV_INSTRUCTION[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"PRIV_INSTRUCTION"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_SINGLE_STEP[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"SINGLE_STEP"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#0000FF]case[/color] EXCEPTION_STACK_OVERFLOW[color=#800000]:[/color]
Ret [color=#800000]=[/color] [color=#800080]"STACK_OVERFLOW"[/color][color=#800000];[/color]
[color=#0000FF]break[/color][color=#800000];[/color]
[color=#800000]}[/color][color=#800000];[/color]
[color=#0000FF]return[/color] Ret[color=#800000];[/color]
[color=#800000]}[/color][color=#800000];[/color]

LONG WINAPI MyExceptionHandler [color=#800000]([/color]PEXCEPTION_POINTERS pExceptionInfo[color=#800000])[/color]
[color=#800000]{[/color]
[color=#0000FF]char[/color] Text[color=#800000][[/color][color=#0000FF]1000[/color][color=#800000]][/color][color=#800000];[/color]
wsprintfA[color=#800000]([/color]Text[color=#800000],[/color]
[color=#800080]"V programu došlo k chybě: %08X %s\n"[/color]
[color=#800080]"Kontaktujte výrobce programu!\n"[/color]
[color=#800080]"Program bude ukončen."[/color][color=#800000],[/color]
pExceptionInfo[color=#800000]-[/color][color=#800000]>[/color]ExceptionRecord[color=#800000]-[/color][color=#800000]>[/color]ExceptionCode[color=#800000],[/color]
TypVyjimky[color=#800000]([/color]pExceptionInfo[color=#800000]-[/color][color=#800000]>[/color]ExceptionRecord[color=#800000]-[/color][color=#800000]>[/color]ExceptionCode[color=#800000])[/color][color=#800000])[/color][color=#800000];[/color]
MessageBoxA[color=#800000]([/color]NULL[color=#800000],[/color]Text[color=#800000],[/color][color=#800080]"Obluha SEH"[/color][color=#800000],[/color]MB_OK[color=#800000]|[/color]MB_ICONERROR[color=#800000]|[/color]MB_SYSTEMMODAL[color=#800000])[/color][color=#800000];[/color]
[color=#0000FF]return[/color] EXCEPTION_EXECUTE_HANDLER[color=#800000];[/color]
[color=#800000]}[/color][color=#800000];[/color]

[color=#0000FF]void[/color] NejakaFunkce [color=#800000]([/color][color=#0000FF]void[/color][color=#800000])[/color]
[color=#800000]{[/color]
[color=#0000FF]char[/color] [color=#800000]*[/color]Ptr [color=#800000]=[/color] NULL[color=#800000];[/color]
[color=#800000]*[/color]Ptr [color=#800000]=[/color] [color=#0000FF]1[/color][color=#800000];[/color]
[color=#800000]}[/color][color=#800000];[/color]

[color=#0000FF]int[/color] WINAPI WinMain [color=#800000]([/color]HINSTANCE hInstance[color=#800000],[/color] HINSTANCE hPrevInstance[color=#800000],[/color] LPSTR lpCmdLine[color=#800000],[/color] [color=#0000FF]int[/color] nCmdShow[color=#800000])[/color]
[color=#800000]{[/color]
[color=#008000]// instalace vlastni obsluhy SEH, [/color]
[color=#008000]// která funguje napric vsemi vlakny programu[/color]
[color=#008000]// tj. v pripada SEH vyjimky je je vyvolana[/color]
[color=#008000]// at uz doslo k vyjimce v kteremkoli vlakne programu[/color]
SetUnhandledExceptionFilter[color=#800000]([/color]MyExceptionHandler[color=#800000])[/color][color=#800000];[/color]
[color=#008000]// vypnuti zobrazovani systemoveho dialogu SEH[/color]
SetErrorMode[color=#800000]([/color]SEM_NOGPFAULTERRORBOX[color=#800000])[/color][color=#800000];[/color]

MessageBoxA[color=#800000]([/color]NULL[color=#800000],[/color]
[color=#800080]"Po uzavření tohoto dialogu dojde k výjimce."[/color][color=#800000],[/color]
[color=#800080]"Před výjimkou"[/color][color=#800000],[/color]
MB_OK[color=#800000])[/color][color=#800000];[/color]

NejakaFunkce[color=#800000]([/color][color=#800000])[/color][color=#800000];[/color]

[color=#0000FF]return[/color] [color=#0000FF]0[/color][color=#800000];[/color]
[color=#800000]}[/color][color=#800000];[/color]
[/code][/size]

Citovat příspěvek

 

Re: Výjimky a thready

Autor: Neon

8:46:35 12.08.2010

Díky za vysvětlení.

To, že výjimka je jednothreadovou záležitostí, jsem nevěděl, takže OK, to je omezení.

Teď to tedy řeším tak, že thr 2 místo výjimky generuje událost, na kterou (mezi jinými) čeká thr 1 pomocí WaitForMultipleObjects(). Text výjimkového hlášení si pak předají přes nějakou proměnnou.

Zajímal by mě i nějaký z "dalších tisíců" řešení (resp. i z takového počtu si myslím, že vhodně použitelné by vyšly tak dva tři).

Neon

Citovat příspěvek

 

Re: Výjimky a thready

Autor: AnonymousUser

3:59:16 12.08.2010

Ještě by bylo dlužno říci, že předání výjimky mezi thready je možné udělat tisíci způsoby. Jste omezeni jen vlastní fantazií.

Důležité je vědět, co se děje.

O tomhle tématu by se dalo povídat hodiny a hodiny a byl by to zajímavý čas.

Citovat příspěvek

 

Re: Výjimky a thready

Autor: AnonymousUser

3:53:45 12.08.2010

Jen stručně:

Výjimky se chytají v rámci stejného threadu. Tečka.

throw výjimky chytí pomocí catch jen ten samý thread

Pokud chcete cokoli jiného, musíte si to naprogramovat.

---

Výjimky typu SEH jsou hloupé „portable“ výjimky přimárně určené vývojářům Windows uvnitř Microsoftu. Ty nakonec byly zpřístupněny i programátorům (což zkomplikovalo přechod na 64 bitů, nakonec museli vývojáři procesorů něco zemulovat, ale to je off topic).

Výjimka typu SEH nenese naprosto žádnou typovou informaci. Nese pouze celé číslo, pole parametrů a kontext plus odkazy na další výjimky.

SEH výjimka, tedy i to co navrhuje pan Valerian, je věcí Windows.

---

C++ výjimka je implementovaná C++ kompilátorem a runtime knihovnami. Může, ale nemusí být postavená na SEHu.

C++ výjimka obsahuje informaci o typu. Jak? To je nedefinováno a je věcí kompilátoru jak to provede.

---

Základní dva závěry:

1) Existuje více typu výjimek, přičemž jen C++ výjimky jdou přirozeně vyhazovat pomocí throw a zaručeně chytat pomocí catch.

2) Výjimka je vnitrothreadová záležitost. Překročit thread neumí. Přenesení informace mezi thready o výjimce je šikovnost a vyčúranost programátora, který jim k tomu uměle pomůže, ovšem bez trikování a trochu snahy to nejde. Přirozeně to try/catch systém nedokáže.

Miloslav Ponkrác

Citovat příspěvek

 

Re: Výjimky a thready

Autor: Neon

21:59:11 11.08.2010

Děkuji za nasměrování, ale stejně nevím.

Takže: ve vedlejším threadu mám volat co nejdříve UnhandledExceptionFilter() s nějakou funkcí (např. myFilter()), která "přefiltruje důvod", proč vznikla výjimka?

Mějme např.

struct MyException { };

Jak v myFilter() poznám, že hážu zrovna "MyException"? Podle kterého z prvků EXCEPTION_POINTERS?

A kterou z hodnot EXCEPTION_EXECUTE_HANDLER, EXCEPTION_CONTINUE_EXECUTION a EXCEPTION_CONTINUE_SEARCH by měla myFilter() vrátit, když pozná, že jde o MyException()?

A to celé stačí, aby se (neobsloužená) výjimka ve vedlejším threadu obsloužila chycením v hlavním threadu?

Neon

Citovat příspěvek

 

Re: Výjimky a thready

Autor: JiriValerian

19:47:13 11.08.2010

[color=#008000]Neon Napsal:
-------------------------------------------------------
> Zdravím v konferenci,
>
> měl bych dotaz - je možno házet/chytat výjimky
> mezi thready?
>
> Tj. - mohu zachytit výjimku v hlavním threadu,
> když výjimku hodí vedlejší thread, který byl
> spuštěn hlavním threadem?
>
> Pokud by výjimka z vedlejšího threadu nešla
> zachytit hlavním threadem, jak to řešit?
>
> - Napadá mě pouze předat si text chybového (=
> výjimkového) hlášení mezi thready přes nějakou
> proměnnou a k tomu se informovat o vzniklé výjimce
> nějakou událostí.
>
> Ale zajímal by mě názor nebo praxe ostřílených
> "multithreadistů", jestli je to to nejlepší, nebo
> jak se taková situace "zpravidla" řeší.
>
> Předem dík.
>
> Neon
>[/color]

[b]SetUnhandledExceptionFilter Function[/b]
Enables an application to supersede the top-level exception handler of each thread of a process.
http://msdn.microsoft.com/en-us/library/ms680634(VS.85).aspx

Citovat příspěvek

 

Výjimky a thready

Autor: Neon

14:50:20 11.08.2010

Zdravím v konferenci,

měl bych dotaz - je možno házet/chytat výjimky mezi thready?

Tj. - mohu zachytit výjimku v hlavním threadu, když výjimku hodí vedlejší thread, který byl spuštěn hlavním threadem?

Pokud by výjimka z vedlejšího threadu nešla zachytit hlavním threadem, jak to řešit?

- Napadá mě pouze předat si text chybového (= výjimkového) hlášení mezi thready přes nějakou proměnnou a k tomu se informovat o vzniklé výjimce nějakou událostí.

Ale zajímal by mě názor nebo praxe ostřílených "multithreadistů", jestli je to to nejlepší, nebo jak se taková situace "zpravidla" řeší.

Předem dík.

Neon

Citovat příspěvek

 

 

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: