Problémy s Shell Extensions: z pohledu AS2.5

Hlášení chyb a problémů programu Altap Salamander. Buďte, prosím, ve svých popisech co nejpodrobnější a vytvořte pro každý incident nový příspěvek. Nevkládejte programem generovaná hlášení o pádu programu, pošlete je e-mailem.
Jan Rysavy
ALTAP Staff
ALTAP Staff
Posts: 5231
Joined: 08 Dec 2005, 06:34
Location: Novy Bor, Czech Republic
Contact:

Problémy s Shell Extensions: z pohledu AS2.5

Post by Jan Rysavy »

S podporou pro overlay icons (od 2.5RC3) jsme narazili na novou vlnu nestability díky TortoiseSVN. Zakládám toto vlákno za účelem prodiskutování možných řešení.

Nezbytné čtení na úvod: Creating Shell Extension Handlers (MSDN). Většina popsaných handlerů se Salamandera týká.

Popis problému (KDY a KDE je voláme):
1. některé shell extension jsou do procesu Salamandera načteny v rámci odbavováni drag&drop a context menu -- v těchto případech nad jejich načtením a vyvoláním nemáme žádnou kontrolu, enumeraci registry, načtení DLL a jejích zavolání provádí Windows v rámci zavolaných API funkcí; tyto běží v našem hlavním vlákně, které odbavuje message queue a kde běží GUI

1.1 častým případem předešlého jsou problémy s otevíráním dokumentů, které jsme se pokoušeli vyřešit pomocí zavolání IContextMenu2::QueryContextMenu() a InvokeCommand() v rámci jiného procesu SALOPEN.EXE

2. implementace overlay icons probíhá kompletně v režii Salamandera, známe seznam všech poskytovatelů a sami je postupně voláme pro každý soubor a adresář (máme šanci vytvořit black/white list); tyto shell extensions načítáme a voláme ve dvou vláknech (levý a pravý panel), které obsluhují načítání ikonek do panelech, viz "apartment threaded" chyba 2.5RC3 opravená v 2.5

3. ze zmíněných dvou vláken pro čtení ikon dochází u některých souborů k získávání ikonek pomocí Icon Handlers; v tomto případě je načtení a vyvolání DLL opět v režii Windows API, jako v případě (1.)

(JAK nám konkrétně škodí)
4. pády bez korupce zásobníku -- ty zachytíme a korektně zobrazíme bug report, ze kterého lze shell extension určite (její DLL je vidět na stacku)

5. korupce zásobníku nebo paměti (shell extension například zapíše do ANSI bufferu na stacku UNICODE string, takže přepíše okolí bufferu; k pádu může dojít v shell extension nebo po návratu) -- tyto pády je problém diagnostikovat

6. shell extension zavolá DestroyWindow() na parent okno, protože tímto způsobem zavírají Windows Explorer okna (dříve jsme podávali handle okna panelu, nyní předhazujeme speciální dočasné child okno, u kterého po návratu detekujeme, zda bylo zavřeno a zobrazíme Bug Report) -- pokud shell extension provede iteraci směrem k main window, stějně dokáže Salamandera přes DestroyWindow sestřelit

7. Windows Media Player, pokud je spuštěn poprvé, zobrazuje úvodní okénko s dotazy na konektivitu atd; toto proběhne v našem hlavním vlákně po zavolání IContextMenu2::InvokeCommand() (viz konkrétní případ); po zavření tohoto okna neukončí svou message loop a pumpuje zprávy ze svého DLL; Total Commander i Windows Explorer celkem bez potíží v tomto stavu fungují, ale Salamander má poměrně komplikovanou obsluhu message queue a pokud se nám do ní hlavní vlákno nevrátí, vzniká problém
Edit: další případ

8. Shell Extensions s oblibou zapomínají zavírat handly na otevřené soubory a adresáře, viz tento problém, kde jsem se pokusil problematiku shell extensions popsat; Salamander následně se souborem nebo adresářem nedokáže pracovat (sám si blokuje přístup) a pomůže až restart Salamandera

9. Icon Handlers dokážou během získávání ikonek spadnout; často tak padají Adobe Photoshop a Illustrator Icon Handlery, vedlo to dokonce na poměrně tvrdou výměnu názorů mezi Adobe a Microsoft (Adobe tvrdil, že Windows Explorer je nestabilní platforma a Microsoft naopak z problému vinil vadný Adobe Icon Handler, což můžeme jen potvrdit); malá ukázka této pohromy: Photoshop a Illustrator

Protože jsou shell extensions nejčastějším zdrojem problémů, připravili jsme kuchařku jak vadné shell extensions dohledat a vyřadit.

Pokud máte nápady na zlepšení současné situace, neváhejte a pište. Rádi také zodpovíme doplňující dotazy.
Last edited by Jan Rysavy on 10 May 2007, 11:19, edited 1 time in total.
manison
Plugin Developer
Plugin Developer
Posts: 216
Joined: 09 Dec 2005, 23:23
Location: Ceske Budejovice, Czech Republic
Contact:

Post by manison »

Nejdřív je třeba si říct, co od Salamandra v tomto směru očekáváme. Chceme, aby Salamander pracoval správně i s chybnými shell extensions nebo aby takové extensions elegantně (rozuměj bez neřízeného pádu) detekoval a příště třeba už nenahrával. Osobně si myslím, že je třeba soustředit se na druhý případ, protože jednak Salamander potřebuje spoustu jiných funkcí, než aby opravoval cizí chyby, a za druhé se dá o účinnosti takového mechanismu dost silně pochybovat (už třeba z toho důvodu, že nad některými extensions nemáte vůbec žádnou kontrolu). Je tedy třeba vylepšit systém detekce a reportování chyb modulů. Záměrně nyní píši modulů, protože s blížícím se vydáním SDK se případy pádů Salamandera rozšíří o ty, způsobené chybně napsanými pluginy.

Níže přikládám k diskuze své nápady:

Salamander by měl na každou neošetřenou výjimku vygenerovat bugreport, doplněný případně o soubor s minidumpem, který lze použít pro post-mortem ladění a obsahuje další důležité informace, které nyní nejsou v reportu obsaženy. Dále, pokud to lze zjistit, by měl Salamander určit modul, ve kterém k výjimce došlo a nabídnout jeho další nenačítání (tj. v případě pluginu jeho dočasné odinstalování, v případě shell extensions nějaký seznam ve stylu dialogu Spravovat doplňky z MSIE).

Ad 5.: Pokud se extension předává buffer, kde toto hrozí (řekněme např. IContextMenu::GetCommandString) - alokovat buffer na heapu (ne na zásobníku, aby se předešlo jeho poškození), 2x větší než je potřeba (ANSI/Unicode problém) + ještě pár bajtů navíc a vyplnit ho nějakým nenulovým vzorem. Pokud je po návratu z metody přepsán vzor tam, kde by neměl, zakázat extension. V novějších překladačích (MSVC 2003+) je dobrá podpora pro run-time kontrolu přetečení buferů, možná by stačilo ponechat toto do té doby, než přejdete na nový překladač.

Ad 6.: Pokud extension zavolá DestroyWindow, není proti tomu už žádná obrana (snad jedině hákování funkce v načítaných modulech). Salamander ale ví, že před WM_DESTROY musí přijít WM_CLOSE (zavření přes křížek v titulkovém pruhu, ze systémového menu nebo menu File, ze správce úloh). Pokud tomu tak není (samozřejmě, extension může sama také poslat WM_CLOSE), měl by to Salamander ohlásit jako chybu a třeba nabonzovat poslední extension, se kterou pracoval. Proč nepředáváte do extension handle nějakého top-level okna? To by pak extension nemohla doiterovat až do hlavního okna Salamandera.

Ad 7.: Pokud by toto způsobovalo velké množství problémů, bylo by třeba zrevidovat Vaši smyčku zpráv. Proč exploreru i TC stačí jednoduchá obsluha, v čem je Vaše odlišná? Jak se stane, že se hlavní vlákno do ní nevrátí?

Ad 8.: Pokud Salamander zjistí zamčený soubor, měl by i zjistit, který proces jej zamknul. Jestliže je sám Salamander viníkem, je to považováno za chybu a může se zase nabídnout poslední extension, se kterou se pracovalo (pokud je známo).

Ad 9.: Jj, extensions od Adobe jsou šmejdy. Dokud jsem je neodinstaloval, tak mi s oblibou snažily číst data z diskety a těžko rozdýchávaly, když v mechanice žádná nebyla.
Post Reply