Here's what I think is really going on:
At the end of a process's execution, 2 things happen:
- The process's code finishes its execution -- wait returns.
- The OS closes the executable file.
The second item always "comes after" the first. On Windows the delay might be a few milliseconds, which can cause a problem, since an attempt to delete the executable right after wait returns can fail because the executable is still open. On Unix, this is not a problem because it's OK to "remove" an open file -- the file doesn't actually get deleted until all openers have closed the file.
At one time, Go's os/exec for Windows had a built-in unconditional 5ms delay to prevent this from happening. Not sure if it still does that.
It seems that, on Windows, if a program wants to delete the executable right after its process has finished, if should put the delete in a little retry loop:
loop a few times (10?)
try do delete the executable
if the delete succeeds
exit this loop
wait a short time (1 ms ?)
announce an error -- executable could not be deleted in reasonable time after process completion
This retry loop would be the responsibility of any Windows program that wants to delete the executable file after its execution finishes.
In reality, this is not done in very many places, done only by some tools like "go run" (build, run, delete), and the occasional user-written tool. The vast majority of places where external processes are run leave the executable file alone after process completion.
Is it the responsibility of an OS like Windows the guarantee the the executable is closed when a process wait returns? I would say not, because that might cause a (small) delay in the vast majority of external process executions where the executable is not deleted immediately after.