There is a race condition when using mktemp() to create unique file names, everybody should be aware of this, no big surprise. The nice thing about most *NIXES is that they actually use random strings substituted into the pattern to create the unique name. With a large enough pattern, you probably won't run into the race condition right away. Not so with Windows.
I found a problem in my thesis project where the clients were returning result files, but the files weren't actually making it where they're supposed to be. They were marked as returned in the DB but the file was missing from the FS. I immediately realized that this was probably a name collision problem with temporary file creation. I switched my unix code base to using mkstemp().... and found out tonight during the test compile that Windows doesn't support mkstemp().
Mkstemp() creates a file for each unique temporary file name and returns its file handle. This avoids the race condition. To make matters worse, Windows generates the 'unique' names sequentially. What happens when a dozen clients show up to upload results? The race condition bites you in the arse and you end up losing result files. The problem is you call mktemp() it returns a unique file name but before your thread gets to create the file, another upload is initiated and the same filename is handed out (because that file doesn't yet exist). When both programs are writing to the same file handle at the same time, you get unpredictable results. In my case, the thread that finishes first copies the file to its 'final' resting place and deletes the temporary one, so the second thread can't complete the copy without errors.
One option is to use GetTempFileName() on windows with the CREATE_NEW flag set and then loop until success.... does that sound like a good solution ? You could end up waiting a very long time before you could create a valid file name - probably the socket would timeout before this happened when the server is busy.
A second solution is to break the temporary directory into sub directories... to lessen the chance of a collision happening. This is almost as much work as solution #3.
Solution #3 is to write your own implementation of mkstemp() using good pseudo-random number generator. I've got the framework in place to do this, so this is the approach I'm going to go with. I do this with some resentment, as I really feel this is a service the OS should handle.
None of my classes at Oklahoma State University covered specifics at this level of detail (Apparently
Purdue does!). Even though we covered race conditions very thoroughly, I still have to learn real-world instances the hard way. ;(
