This is VC++ 6.0 code running on a Windows Server 2003 SP2 machine.
1. I launch an external exe from my code using CreateProcess()
2. This process creates a file on disk
3. I do rc = WaitForSingleObject(procInfo.hProcess,INFINITE);
4. rc is returned as WAIT_OBJECT_0
5. int result = _stat( strDestFile, &buf ) where strDestFile is the file from step #2
6. I get _size as 0. However, when I execute the same exe as in step 1 standalone from a console window, it generates the file fine and it's not empty.

QUESTION: is it possible that _stat is returning incorrect info? Is there a more reliable way to check for non-0 size? Is there a way to check whether strDestFile has been properly closed by the external exe?

Thanks much!!!

Dani AI

Generated

This is almost certainly a timing/race issue rather than a broken _stat. 's race-condition hint is the right direction: WaitForSingleObject(procInfo.hProcess, INFINITE) only guarantees the specific process handle you waited on has terminated. That process may have spawned a child that does the actual writing, or it may have left asynchronous I/O or caching pending. already checking _stat's return and errno is good — _stat reports what the OS metadata shows at the call moment.

Practical checks to diagnose the problem:

If a more reliable size check is needed, query the Win32 APIs directly instead of CRT wrappers. Example pattern:

HANDLE h = CreateFileA(path, GENERIC_READ,
                       FILE_SHARE_READ | FILE_SHARE_WRITE,
                       NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h != INVALID_HANDLE_VALUE) {
    LARGE_INTEGER size;
    if (GetFileSizeEx(h, &size)) {
        // size.QuadPart is file length
    }
    CloseHandle(h);
}

To detect whether some process still has the file open, try opening it exclusively (no sharing). If CreateFile fails with ERROR_SHARING_VIOLATION the file is locked:

HANDLE h = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (h == INVALID_HANDLE_VALUE && GetLastError() == ERROR_SHARING_VIOLATION) {
    // file currently held by another process
}

Best practices to avoid this class of bugs: have the writer write to a temp name and rename to the final name when complete (atomic move), call FlushFileBuffers before closing if possible (FlushFileBuffers docs), or arrange to wait for all real worker processes (job objects can help if you control process creation — see Job Objects). If changing the writer is impossible, poll with a short delay until the size is stable or try the exclusive-open/rename probe above.

Recommended Answers

All 2 Replies

Seems like this to me
http://en.wikipedia.org/wiki/Race_condition

> 5. int result = _stat( strDestFile, &buf ) where strDestFile is the file from step #2
> 6. I get _size as 0
Ah, but what was in result?

if( result != 0  && errno == ENOENT) {
	// file does not exist
} else if ( buf.st_size == 0)
	// exists but empty
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.