Izolacja sterowników drukarek

Im glebiej wchodzi sie we wnetrznosci systemu, tym dokladniej mozna zobaczyc, ze proces jest bardzo specyficznym obiektem. Tak naprawde nie ma on wiele wspólnego z dzialaniem aplikacji (tutaj duzo ciekawsze sa watki) ale przede wszystkim z zarzadzaniem tym, co w systemie sie dzieje. Temat jest ogromny i zainteresowanych chyba najlepiej odeslac do "Windows Internals" a dokladniej do rozdzialu piatego: "Processes, Threads, and Jobs". To, co jest dzisiaj dla mnie wazne, to sposób podejscia systemu Windows do sytuacji, kiedy cos zachowuje sie nieladnie. W trybie jadra konczy sie to Blue Screenem, a poza tym trybem – Windows po prostu "zabije" tego, kto mu podpadnie. I choc wykonywane sa poszczególne watki i to watek cos niedobrego zwykle robi – zabity zostanie caly proces. Tak jest prosciej, bezpieczniej i z punktu widzenia administratora jest to latwiejsze do ogarniecia. Problem polega jednak na tym, ze skutkiem zastosowania odpowiedzialnosci zbiorowej jest to, ze razem z watkiem wadliwym, zakoncza sie i inne, które w ramach tego samego procesu zachowywaly sie zupelnie poprawnie. Jezeli dzieje sie tak w jakiejs aplikacji od poczatku do konca przygotowanej przez jednego programiste – trudno. Niech cierpi za slaba obsluge bledów.

Powazniejszy problem pojawia sie wtedy, gdy aplikacja musi zaladowac moduly napisane przez kogos innego. Oznacza to, ze w ramach procesu pojawiaja sie watki, dla których kod wykonywalny pochodzi nieraz z zupelnie nieznanego zródla. I moze zdarzyc sie, ze taki watek z zewnetrznej biblioteki zachowa sie nieladnie. Wtedy system zabije caly proces, razem z podpadnietym watkiem i wszystkimi innymi watkami, które mogly robic cos istotnego. Sytuacja taka zdarza sie w praktyce w niemal w kazdym systemie. Na przyklad, w kazdym, w którym ktos chce drukowac. W systemie Windows 2008R2, wyglada to domyslnie tak, ze usluga spooler (bufor wydruku) laduje specjalna biblioteke DLL (PrintIsolationProxy.dll), która laduje sterowniki drukarek.

pdi01

Blad w sterowniku powoduje zabicie procesu. Skutki sa proste do przewidzenia: usluga spooler przestaje dzialac i nikt w tym systemie nic juz nie wydrukuje dopóki nie zostanie uruchomiona ponownie. Dlatego wlasnie, w systemie Windows Server 2008 R2 mozna skonfigurowac system tak, aby dla danego sterownika spooler zachowywal sie nieco inaczej. Zamiast bezposrednio ladowac biblioteke PrintIsolationProxy.dll, uruchomi specjalny proces (PrintIsolationHost.exe) który zaladuje biblioteke, która zaladuje sterowniki.

pdi02

A gdy sterownik zachowa sie nieladnie? Cóz... Proces PrintIsolationHost.exe zostanie zabity. A spooler przezyje. Co wiecej, mozna równiez calosc ustawic tak, aby PrintIsolationHost.exe uruchamiany byl dla kazdego sterownika oddzielnie. Wtedy jeden sterownik moze "wywracac sie" chocby i kilka razy na sekunde a inne pozostana niewzruszone. Z punktu widzenia uzytkownika, korzysc jest oczywista: mozna drukowac.

Calosc jest bardzo prosta do skonfigurowania. Z konsoli "Print Management" wystarczy wybrac galaz "Drivers", i z menu kontekstowego dla sterownika wybrac jeden z trzech poziomów izolacji:

  • None – sterownik ladowany jest w procesie spoolera
  • Shared – sterownik jest izolowany od spoolera, ale nie od innych sterowników w trybie "shared", z którymi wspóldzieli jeden proces
  • Isolated – sterownik ma wlasny proces izolujacy.

pdi03

A dlaczego w ogóle nie rozwiazac tego tak, zeby kazdy sterownik zawsze mial wlasna pule? Dlatego, ze takie odizolowanie nie jest "za darmo". Wymaga wiecej CPU, zajmuje pamiec tworzy wiecej procesów... A awaryjne sterowniki az tak czesto sie nie zdarzaja.

Sterownik moze sam z siebie zazadac uruchomienia w trybie izolacji i wtedy zamiast domyslnego poziomu "None" uzywany jest inny. Przy czym zadanie takie system moze zignorowac, na przyklad w sytuacji, gdy w GPO ustawione sa wpisy Execute Print Drivers in Isolated Processes i Override Print Driver Execution Compatibility Setting Reported by Print Driver w galezi Computer Configuration\Administrative Templates\Printers

Warto równiez wiedziec o galezi rejestru HKLM\SYSTEM\CurrentControlSet\Control\Print\ i wpisach PrintDriverIsolationIdleTimeout, PrintDriverIsolationTimeBeforeRecycle oraz PrintDriverIsolationMaxobjsBeforeRecycle. Okreslaja one, kiedy proces izolujacy jest usuwany lub restartowany. Pozwala to uwolnic troche pamieci gdy system nie uzywa danego sterownika lub skorzystac z tego, ze restart procesu oznacza ponowne zaladowanie sterowników i w ten sposób zapobiec wyciekom pamieci.

Udanego izolowania!

Autor: Grzegorz Tworek [MVP]