On Windows, keep the lifetime of relative pathnames as short as possible because of thread-safety issues
Posted by jpluimers on 2022/05/18
Subtitle:
GetFullPathNamethread-unsafety because ofSetCurrentDirectoryisn’t, so derived functions (like DelphiGetDir/ChDir/TPath.GetFullPath, or .NETSystem.IO.Path.GetFullPath) are not thread-safe either (via The Old New Thing)
A while ago I got a big reminder because of [Wayback] What are these dire multithreading consequences that the GetFullPathName documentation is trying to warn me about? | The Old New Thing:
The documentation for the
GetFullPathNamefunction contains this dire warning:Multithreaded applications and shared library code should not use the
GetFullPathNamefunction and should avoid using relative path names. The current directory state written by theSetCurrentDirectoryfunction is stored as a global variable in each process, therefore multithreaded applications cannot reliably use this value without possible data corruption from other threads that may also be reading or setting this value. This limitation also applies to theSetCurrentDirectoryandGetCurrentDirectoryfunctions. The exception being when the application is guaranteed to be running in a single thread, for example parsing file names from the command line argument string in the main thread prior to creating any additional threads. Using relative path names in multithreaded applications or shared library code can yield unpredictable results and is not supported.
Boy, this was a trip down memory lane, as subconsciously I was aware of this, but not consciously, so it was great seeing it all written down.
Since most of your Windows applications and services are multi-threaded by now (even if you don’t realise this, a cmd.exe instance already has multiple threads running).
It means that the current directory global process variable can be changed by any thread. Since GetFullPathName relies on this converting relative pathnames to absolute pathnames, it means that over time the conversion might give you different absolute pathnames.
Which means these all are not thread-safe:
- Windows API
- .NET
- Delphi XE2 and up:
- Delphi 2010-XE (before namespaces were introduced):
- Turbo Pascal 3 and up, including any Delphi versions:
Related: Much Turbo Pascal history (via What is a Delphi DCU file? – Stack Overflow)
–jeroen






Leave a comment