Subtitle:
GetFullPathName
thread-unsafety because ofSetCurrentDirectory
isn’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
GetFullPathName
function contains this dire warning:Multithreaded applications and shared library code should not use the
GetFullPathName
function and should avoid using relative path names. The current directory state written by theSetCurrentDirectory
function 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 theSetCurrentDirectory
andGetCurrentDirectory
functions. 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