4

We have a problem in production with a Windows application written in a mix of C and C++ where MoveFileEx occationally reports "The process cannot access the file because it is being used by another process.". The problem is rare but recently we have been able to reproduce the problem in our development environment. What happens is that process A receives data over the network and creates a file with that data using:

fd = _open(fileName, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, _S_IREAD | _S_IWRITE);
...
while (data on network) {
    write(fd, buffer, count);
}
...
int close_result = _close(fd);

After this Process A opens the file for reading and closes it again. Process A then, without exiting, creates process B. Under very high load, with many threads in A and many B processes in parallel, each handling hundreds of MB, process B sometimes gets the MoveFileEx problem. When I run Process Monitor to capture file system activity I can see that when we get the problem the above mentioned _close(fd) is called and returns no error, but Process Monitor does not register any CloseFile operation from process A for that _close(fd) call. It seems as the _close(fd) call does not reach the operating system. Have anyone encountered a problem like this? Any ideas what to try to fix this? I have tried using fopen instead of _open and different kind of flush calls, but nothing seems to help.

  • Are you sure that the problem is not because of some synchronization issue between process A and process B? – montonero Dec 28 '18 at 11:12
  • I am not sure what you are looking for. You want your file to be closed after `_close(fd)` ? I think file won't be closed until there is even a single process left using the file. – restless_soul469 Dec 28 '18 at 11:13
  • You say that process A creates process B only *after* closing the file, but you also mention that process A is multithreaded. How do you ensure the happens-before sequence between closing the file and creating the new process? Are both operations sequenced by running on the same thread one after the other? If not, how else are they sequenced? – EOF Dec 28 '18 at 11:16
  • 2
    You're not opening the file with `_O_NOINHERIT`. Does process B inherit inheritable handles (e.g. `CreateProcess` with `bInheritHandles`)? – Eryk Sun Dec 28 '18 at 19:03
  • Thanks eryksun, adding _O_NOINHERIT to the _open call did the trick!! Now it seems to work. – Krister Valtonen Jan 04 '19 at 08:37

1 Answers1

2

It's noteworthy do add that Microsoft's implementation of fopen() also supports file non-inheritance if you specify N flag in addition to all other flags. Essentially it passes _O_NOINHERIT internally to _open.

This is case someone wants to use buffered I/O in C runtime, such as fwrite, fputs etc (instead of _open/write/_close). I added this note after spending a few hours on research, so I thought it might be worthy to have it here also for someone's reference.

fcdt
  • 2,371
  • 5
  • 14
  • 26
fmike7
  • 56
  • 5