12

Is there a way to bypass or remove the file lock held by another thread without killing the thread?

I am using a third-party library in my app that is performing read-only operations on a file. I need a second thread read the file at the same time to extract out some extra data the third-party library is not exposing. Unfortunately, the third-party library opened the file using a Read/Write lock and hence I am getting the usual "The process cannot access the file ... because it is being used by another process" exception.

I would like to avoid pre-loading the entire file with my thread because the file is large and would cause unwanted delays in the loading of this file and excess memory usage. Copying the file is not practical due to the size of the files. During normal operation, two threads hitting the same file would not cause any significant IO contention/performance problems. I don't need perfect time-synchronization between the two threads, but they need to be reading the same data within a half second of eachother.

I cannot change the third-party library.

Are there any work-arounds to this problem?

James Schek
  • 17,844
  • 7
  • 51
  • 64
  • 6
    A lock is a lock - if there was, it wouldn't be a lock... – Aviad P. Dec 29 '09 at 23:42
  • 1
    And like with many locks, it seems some library developers don't understand that less is more. :-) I'd also be happy with a clever work-around. – James Schek Dec 29 '09 at 23:55
  • 4
    A long shot: can you open that file as shared _before_ your 3rd-party library? Maybe they implemented some fallback mechanism. – Rubens Farias Dec 30 '09 at 00:02

7 Answers7

5

If you start messing with the underlying file handle you may be able to unlock portions, the trouble is that the thread accessing the file is not designed to handle this kind of tampering and may end up crashing.

My strong recommendation would be to patch the third party library, anything you do can and probably will blow up in real world conditions.

Sam Saffron
  • 128,308
  • 78
  • 326
  • 506
2

In short, you cannot do anything about the locking of the file by a third-party. You can get away with Richard E's answer above that mentions the utility Unlocker.

Once the third-party opens a file and sets the lock on it, the underlying system will give that third-party a lock to ensure no other process can access it. There are two trains of thought on this.

  • Using DLL injection to patch up the code to explicitly set the lock or unset it. This can be dangerous as you would be messing with another process's stability, and possibly end up crashing the process and rendering grief. Think about it, the underlying system is keeping track of files opened by a process..DLL injection at the point and patch up the code - this requires technical knowledge to determine which process you want to inject into at run-time and alter the flags upon interception of the Win32 API call OpenFile(...).
  • Since this was tagged as .NET, why not disassemble the source of the third-party into .il files, and alter the flag for the lock to shared, rebuild the library by recompiling all .il files back together into a DLL. This of course, would require to root around the code where the opening of the file is taking place in some class somewhere.

Have a look at the podcast here. And have a look here that explains how to do the second option highlighted above, here.

Hope this helps, Best regards, Tom.

t0mm13b
  • 34,087
  • 8
  • 78
  • 110
1

This doesn't address your situation directly, but a tool like Unlocker acheieves what you're trying to do, but via a Windows UI.

Richard Ev
  • 52,939
  • 59
  • 191
  • 278
1

Any low level hack to do this may result in a thread crashing, file corruption or etc.

Hence I thought I'd mention the next best thing, just wait your turn and poll until the file is not locked: https://stackoverflow.com/a/11060322/495455


I dont think this 2nd advice will help but the closest thing (that I know of) would be DemandReadFileIO:
IntSecurity.DemandReadFileIO(filename);

internal static void DemandReadFileIO(string fileName) 
{
   string full = fileName;            
   full = UnsafeGetFullPath(fileName); 
   new FileIOPermission(FileIOPermissionAccess.Read, full).Demand();
}
Community
  • 1
  • 1
Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
1

I do think that this is a problem that can be solved with c++. It is annoying but at least it works (as discussed here: win32 C/C++ read data from a "locked" file)

The steps are:

  1. Open the file before the third-library with fsopen and the _SH_DENYNO flag
  2. Open the file with the third-library
  3. Read the file within your code

You may be interested in these links as well:

  1. Calling c++ from c# (Possible to call C++ code from C#?)
  2. The inner link from this post with a sample (http://blogs.msdn.com/b/borisj/archive/2006/09/28/769708.aspx)
Community
  • 1
  • 1
ymz
  • 6,602
  • 1
  • 20
  • 39
1

Have you tried making a dummy copy of the file before your third-party library gets a hold of it... then using the actual copy for your manipulations, logically this would only be considered if the file we are talking about is fairly small. but it is a kind of a cheat :) good luck

Neil Dick
  • 11
  • 2
1

If the file is locked and isn't being used, then you have a problem with the way your file locking/unlocking mechanism works. You should only lock a file when you are modifying it, and should then immediately unlock it to avoid situations like this.

holtc
  • 1,780
  • 3
  • 16
  • 35