iso file locking
I'm doing iso image writing following the sdk sample code - converted to use ATL.
After the write, which completes with success, the function is exited, and all the atl objects seem to go out of scope with no leaks that I can see. Outside of the function, I try to delete the iso, but DeleteFile fails with a GetLastError():
"The process cannot access the file because it is being used by another process."
Is there some kind of Close() call I need to be calling on one of the interfaces?
(IDiscFormat2Data orIStream maybe?)
[637 byte] By [
foobarX] at [2008-2-6]
You need to call Release on all the COM interfaces you AddRef or QueryInterface. Did you miss one?
Hi FooBarX,
I've seen random file locking issues with various anti-virus (AV) programs. Can you help us understand if this occurs only as a timing-related problem (i.e. if the program sleeps for ten minutes before attempting to delete, will it work)? Of course, it's also possible some code path is not cleaning up its handles properly.
Also, if you use the FileSpy utility from http://www.osronline.com/article.cfm?article=370, does that help shed any additional light on who might have an open handle to the file?
Can you simplify a repro case into the fewest possible steps for us to try and repro?
Hoping this helps track down the root cause....
.
I'm using ATL to help ensure this (since I am throwing exceptions and am worried about leaks of various types.)
The one area of vulnerability may be because of a type cast operator I am thinking...
This is representative of what I'm doing - the stream part follows the psdk sample:
CComPtr<IDiscFormat2Data> dataWriter;
CoCreateInstance(CLSID_MsftDiscFormat2Data, NULL, CLSCTX_ALL, IID_PPV_ARGS(&dataWriter));
CComPtr<IStream> dataStream;
GetIsoStreamForDataWriting(&dataStream, §orsInDataStream, filename);
//defined as HRESULT GetIsoStreamForDataWriting(__out IStream** result, __out ULONG* sectors2,
//const
WCHAR * shortStreamFilename) //this function ends up calling SHCreateStreamOnFile(LPCTSTR pszFile, DWORD gfrMode, IStream **ppstm)
dataWriter->Write(dataStream);
It all functions properly (HRESULTS checked.) Will that dataStream release properly as it goes out of scope?
I don't have any AV running.
I'll try FileSpy, but I'm not hopeful, because I already know for sure that my process is what is locking the file - I had checked with a handle utility.
I included the basic steps I am taking in the reply to Dave above. So far, I only need to go through this code once per process run, so the lock is apparently released by the next run, but I'm not sure if it is just win32 process space cleanup that is doing it or not...
Hi FooBarX,
Since you don't have any AV running, and you've verified it's your own process, it seems that your debugging efforts are spot-on. As for debugging this issue, I suggest stepping through the code in the debugger. In particular, you can trace the refcounts by disassembling the AddRef() function of the IStream to find the refcount and setting a Break-On-Write breakpoint ("ba w4 <address>" in ntsd/windbg/kd). This should give you clear indications of when the addref/release occurs.
You say you call:
CComPtr<IStream> dataStream;
GetIsoStreamForDataWriting(&dataStream, §orsInDataStream, filename);
//HRESULT GetIsoStreamForDataWriting(
// __out IStream** result,
// __out ULONG* sectors2,
// const WCHAR * shortStreamFilename
// )
What is the refcount immediately after calling ShCreateStreamOnFileEx()? It should be one, since it's just created. Then, trace through the refcounts as this goes up through the return from this function to ensure that, once the call has completed, the refcount is still 1.
Unfortunately, I've not found a really easy way to deal with refcount issues, so the above "ba w4 <address>" is likely your best debugging solution. Please note that this is outside the scope of IMAPIv2, and general technical support is not the intention of these forums.
Thanks for the ideas Henry.
I guess I'll have to leave my comfy app debugger world and give it a try. A while ago I used to use SoftIce some, but I haven't used ntsd for anything other than killing processes...
Understood that if it is just atl / reference issue it is beyond the scope of IMAPI2 - I just thought there might be some common mistake related to stream references. It sure would be strange to be doing an assymmetrical explicit release for an "auto" object.
Just an FYI at this point - Vista will not let filespy run...
"Cannot install the FileSpy filter driver Access is denied"
Maybe, some UAC adjustment would allow it...?
Reverting back to raw pointers (away from atl) and doing an extra ->Release() (beyond the one I assumed was needed) unlocked the file.
Unfortunately, I need to follow up on the cause and either find a way to revert to atl (->Release() not allowed, and .Release() seems incorrect), or put in extra manual releasing code all over to make it exception safe.
I still yet am not sure what did the AddRef(), the ShCreateStreamOnFile() or the Write().
The objects are pretty opaque when trying to debug them - I think there must be some tips on debugging atl I am missing (especially CComPtr in this case.)
i.e. determining the exact address to put the watch on in the kernel debugger was not even obvious :-)
Are you running the x86 version of Vista, or the x64? (I'm wondering if it possibly be a driver signing issue?) If it's x86, try running setup as administrator...
After "fixing" this I happily moved on, only to discover to my dismay that when running debug binaries outside of the debugger, my code crashes somewhere.
It turns out that it is crashing on the extra release call. Different behavior inside vs outside the debugger.
If I have to choose between a locked file in the debugger vs a crash outside the debugger I know which I'll take. Now to check the release build :-|
It would be better to have an understanding of what is happening here.
At first I thought it was a multithreading/timing issue, but trace statements spell it out pretty clearly where the crash is happening (in a repeatable, consistent fashion.)