4

Ok guys, this one is a tough one.

The scenario:

  • I have multiple services running on multiple machines
  • Each service has multiple threads, and each thread writes a file on a FILER - the shared storage used by my machines (using a share such as \\filername\foo\bar)
  • The FILER machine is a NetApp machine
  • Both the FILER and the machines running the services are using SMB2 (http://en.wikipedia.org/wiki/Server_Message_Block)
  • The instruction used to write the file is as simple as the one listed below in [THE CODE]

[THE CODE]

using (StreamWriter outfile = new StreamWriter(pathToTheFile, false))
{
  outfile.Write(stringToWriteInTheFile);
}

[/THE CODE]

The problem:

Sometimes the service remains "stuck" on this instruction. The error given is:

The process cannot access the file '\\filername\foo\bar\myfile.txt' because it is being used by another process.

After some of these errors, the service refuses to release the lock on the file. What happens then?

You can delete the file, but the file is IMMEDIATELY recreated. Like if a sort-of permanent Stream is alive and keeps writing the file indefinitely.

You can stop the service: it's stuck, and won't be stopped, so I forced a Thread.Abort (yeah, I know but practice, but what else?) after 2 minutes.

So, the service is now stopped, but the machine retains an handle to the file and you CANNOT kill the process keeping the handle alive except by rebooting the machine. . .

I don't know what to do right now, I think I tried everything.

Considerations:

Previously, the FILER and the machines were using SMB1, and this problem never arised. So I guess something fishy happens in the background, but I can't understand what...

I changed recently the code used to write the file, in a desperate attempt to "delegate" everything to .net. Now it's:

File.WriteAllText(pathToTheFile, stringToWriteInTheFile);

but my gut feeling is that, under the wraps, .net is doing the exact same thing - the change is quite recent though, so I can't still say if the "fix" is working or not.

EDIT (as per Vash comment): Usually the file is different, but it can happen (and it actually happens) sometimes that multiple threads are trying to write the same file, however :( - doing the File.WriteAllText shouldn't take care of concurrency issues?

sh0uzama
  • 582
  • 1
  • 6
  • 17
  • 1
    The file, is it always the same file or is each service or thread writing to its own file? I fear that accessing the same file from a lot of different sources will lead to deadlocks anyway, a solution is to handle the write requests completely different. – Alex Apr 17 '11 at 10:37
  • @Vash: Usually the file is different, but it can happen (and it actually happens) sometimes that multiple threads are trying to write the same file, however :( - doing the File.WriteAllText shouldn't take care of concurrency issues? – sh0uzama Apr 18 '11 at 15:28
  • 1
    File.WriteAllText will not necessarily eliminate concurrency issues. It's a convenient shortcut for opening a file, writing content to it, and then closing it. But without "locking" the file, (1) some other process/thread may already have the file open when you go to open it (2) some other process/thread may open the file while you're writing to it. Opening the FileStream object with FileShare.None should (hopefully) eliminate these issues. – David Apr 19 '11 at 13:37
  • 1
    Information about the internals of File.WriteAllText found in this [answer](http://stackoverflow.com/a/6805833/945456). – Jeff B May 27 '16 at 16:06

1 Answers1

2

Try explicitly opening a FileStream in "exclusive" mode, ie

using (var fs = new FileStream("path", 
                              FileMode.Open, FileAccess.ReadWrite, 
                              FileShare.None))
{
    using (var sw = new StreamWriter(fs))
    {
        ...

Of course your code will have to anticipate that the file might be locked when it goes to write it and react appropriately. That part is left as an exercise for the reader :-)

Disclaimer: I have used this in a multi-threaded environment, but I can't guarantee it will work over Samba.

David
  • 2,226
  • 32
  • 39
  • Thank you David, I will try. As I suspected, the File.WriteAllText does exactly what I was doing before, so I guess it won't solve anything. I'll let you know. – sh0uzama Apr 19 '11 at 08:09
  • UPDATE: I just have the confirmation that File.WriteAllText isn't the correct solution. I will implement your suggested solution and will let you know. – sh0uzama Jun 16 '11 at 16:45