Quando pensare all’antivirus

Matteo - 20 nov 2006 23:24

Ci sono casi molto particolari in cui su Windows un antivirus può diventare deleterio per i vostri programmi Win32. Anche se voi non usate un antivirus o se con il vostro specifico non si presentano, potrebbe essere un punto su cui riflettere per evitare che un cliente abbia problemi.

Oggi ci si è presentato questo problema su un pezzo di codice legacy, che non era possibile modificare: viene scelto un nome per un file temporaneo e si entra in un ciclo di calcolo in cui questo file viene creato, riempito di dati, letto e cancellato. Il ciclo viene ripetuto N volte con N qualunque. Ad una iterazione casuale però su alcune macchine il calcolo falliva perché la creazione o l'apertura in scrittura del file restituivano un errore di accesso negato (codice 5 dal CreateFile per la creazione) o di violazione di condivisione (codice 32 dal CreateFile per l'apertura in scrittura, dopo la creazione che ha avuto successo).

Dopo vari tentativi scopriamo che il problema era legato all'uso su quelle macchine dell'antivirus McAfee. Non solo esso rallenta moltissimo l'elaborazione in questo caso, ma addirittura a volte la blocca perché nel momento in cui il file viene cancellato (con DeleteFile) o creato, l'antivirus fa dei controlli sulla validità dell'operazione (che esso sia temporaneo non fa evidentemente differenza) che lo rendono temporaneamente non disponibile per essere subito ricreato (da DeleteFile a CreateFile) o riaperto in scrittura (da CloseFile a CreateFile).

I problemi di questo pezzo di codice sono evidenti: è assolutamente ingiustificato gestire i file temporanei in questo modo; sarebbe molto più corretto e performante se la creazione e la cancellazione dei file fossero fatte fuori dal ciclo interno che dovrebbe invece contenere scrittura, lettura ed eventualmente un "reset" del file prima del ciclo successivo.

Come detto, tuttavia, non avevamo possibilità di modificare così radicalmente questo codice che viene da anni fa. È stato quindi necessario trovare un work–around.

Abbiamo scoperto che per evitare il problema è necessario utilizzare nei CreateFile i flag di condivisione per scrittura, lettura e ANCHE cancellazione: ovvero specificare come terzo parametro FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE (sia per la creazione che per le aperture in lettura o scrittura). Poi per cancellare il file è necessario prima rinominarlo e QUINDI procedere alla chiamata di DeleteFile col nuovo nome, che in ogni caso la Microsoft indica come unica procedura totalmente sicura per la cancellazione di un file in una nota di cui purtroppo al momento non trovo il link.

Alla fine comunque abbiamo scelto una via ancora più semplice perché anche quella soluzione sarebbe stata troppo intrusiva per il codice legacy in quanto le funzioni che aprono file temporanei sono le stesse che aprono file qualunque e non eravamo intenzionati a concedere ciecamente la condivisione dei file comuni in lettura ma soprattutto scrittura.

Così alla fine abbiamo optato per una soluzione molto semplice: aggiungere al nome del file temporaneo una estensione formata da un indice intero incrementato ad ogni DeleteFile: in questo modo ogni ciclo opera su un file diverso e non ci possono essere problemi di condivisione, senza per questo dover generare ogni volta l'intero nome del file temporaneo — nel nostro caso una operazione relativamente onerosa.

 
Weblog Koan Progetti Foto Contatti DW.net map