Temp files are failed to be delete when exception is thrown

Aug 16, 2008 at 2:32 AM
Hi,

I have a windows service monitoring a folder (files are consistently dumped into), and archive them based on the file names.
But I keeping getting this problem, that the C: drive is run out of space. Finally I found out that:
1. DotNetZip won't clean the temp files in C:\Windows\Temp if an exception is thrown when doing zip.Save(). Am I doing something wrong that caused this?
2. The exception is DotNetZip cannot access that file because the file is locked by another process. This is probably true, but the files are coming from another computer through network share.
I haven't read DotNetZip's src code, but I am guessing it's opening the file in write mode??? but why? could someone explain this to me?

Here is my code:
There is no doubt that the zip file does exist all the time, so there is no way ZipFile.Read(zipFileFullName) will fail, and I have never got such exception.
                            try
                            {
                                using (ZipFile zip = ZipFile.Read(zipFileFullName))
                                {                                   
                                        zip.ForceNoCompression = true;

                                        foreach (string fn in (ArrayList)flitem.Value)
                                        {
                                            //Logger.Append("ZIPPING", fn);

                                            zip.UpdateFile(fn, flitem.Key.ToString() + '-' + toDay + "_done");
                                        }
                                        zip.Save(zipFileFullName);                                 
                                    Logger.Append("ZIP_COMPLETED", zipFileFullName);
                                }
                            }
                            catch (Exception ex)
                            {
                                Logger.Append("ZIP_FAILED", ex.Message);
                            }   

Thanks in advance,

Jiang
timobj@gmail.com
Coordinator
Aug 19, 2008 at 12:21 AM
Edited Aug 19, 2008 at 1:35 AM
I'll have to look into this one...
There is already a workitem 5043 covering the problem of leaving temp files when an exception occurs.
I can fix that. 

But that is not the origin of your problem, is it? 

Your primary problem seems to be that DotNetZip is experiencing an exception in the Save() call.  I don't know why that would be.  I will have to look into this further.

Coordinator
Aug 19, 2008 at 1:40 AM
I haven't read DotNetZip's src code, but I am guessing it's opening the file in write mode??? but why? could someone explain this to me?

Not correct. The library calls OpenRead() on the file.

Aug 19, 2008 at 3:38 AM
Hmm... then that's weird...

The following is part of my log files...

If the files are successfully zipped, it will say:
[8/15/2008 5:58:12 AM][ZIPPING]: D:\nuclear\mass_files\BROWNSTEIN_BETTINA-08-15-2008_done.zip
[8/15/2008 5:58:16 AM][ZIP_COMPLETED]: D:\nuclear\mass_files\BROWNSTEIN_BETTINA-08-15-2008_done.zip

when it failed, it gave me the following:
[8/15/2008 5:59:54 AM][ZIPPING]: D:\nuclear\mass_files\BROWNSTEIN_BETTINA-08-15-2008_done.zip
[8/15/2008 5:59:57 AM][ZIP_FAILED]: The process cannot access the file 'D:\export\BROWNSTEIN_BETTINA.CT.PET_PETCT_WHOLEBODY_(ADULT).3.223.2008.08.15.05.27.09.163750.1513533.IMA' because it is being used by another process.

I don't know if this helps.

Thanks for taking a look at this,

Jiang
Aug 19, 2008 at 3:45 AM
By the way, I ended up doing this:

Use the following function to check if the file is locked by another process or not, if it is, ignore this file.

bool IsFileLocked(string filename)
{
    try
    {
        FileInfo file = new FileInfo(filename);
        using (file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None))
        {
             return false;
        }
    }
    catch (IOException)
    {
         return ture;
    }
}


Ref: http://forums.msdn.microsoft.com/en-US/csharpgeneral/thread/ea40a788-3220-41ba-ba14-d5fb19275614/

Thanks,

Jiang

Aug 19, 2008 at 4:07 AM
Sorry, I didn't know this is a duplicate item.
I didn't submit the original one, 5043.

Thanks,

Jiang
Coordinator
Aug 19, 2008 at 3:03 PM

about the duplicate item, No apologies necessary.  I Was only fessing up that someone else had previously complained about this behavior (leaving junk around when exceptions occurred during save), and that I had not fixed it.

About the OpenRead() thing - I believe you that DotNetZip cannot open the other file. It's not weird to me; I suspect that the other process hasn't finished writing the file, when DotNetZip tries to open it for reading.  See, it is possible for a process to open a file in "exclusive mode", which prevents other processes from reading the file.  This is the normal course of action when creating a file, for example.  Could it be that your app is "seeing" the new file before it is finished being written?  Could it be that your zip app is trying to open the file too soon?

I like your workaround.  It will prevent the exception in the Save method.  But, you will miss that one file. 

You may want to add in a back-off approach, where you try to open the file, and if that fails, you wait for a short period (let's say, 100  milliseconds), then you try again.  If that fails, you wait 200 milliseconds, and try again.  And again and again, until you've waited maybe 1-2 seconds for the file.  And then give up (return false from IsFileLocked()) only if you've still got a failure at that point.  The total backoff interval should be determined by the characteristics of the other process - how long does it take for the other process to save a file?  You probably want your total backoff interval to be 2x that time. 

But this is just an idea; you understand the situation more clearly than I do.