windowswinapisynchronization

When does windows signal a process handle?


I have a self upgrade process implemented where my main application exe launches an updater exe passing a handle to itself on the command line. The application exe then calls ExitProcess to exit, and the updater calls WaitForSingleObject on the passed in handle to wait for the application exe to terminate.

The WaitForSingleObject does wait. Until the application calls ExitProcess the updater does stall.

However, sometimes, when the updater tries to overwrite the application dlls with the new versions I get a file-locked error which the current version of my updater treats as an unrecoverable error and terminates. It seems that including an arbitrary sleep(100) is sufficient to bypass this "issue" but I really hate code like that. really hate.

It seems very odd to me that the process handle can be signalled while the main application is still alive enough to have dll files locked.


Solution

  • As another answer points out, the process handle gets signalled when the process has stopped execution, and the operating system might take a bit longer to release DLLs.

    You are right that relying on Sleep(100) is a bad idea. You should rather wrap overwriting your DLLs in a loop like this:

    BOOL UpdateDll(LPCTSTR dll_name, WHATEVER whatever) {
      int tries = 150;
      while (tries--) {
        if (TryUpdateDll(dll_name, whatever))
          return TRUE;
        Sleep(200);
      }
      return FALSE;
    }
    

    This keeps trying to unload your DLL for 30 seconds and then gives up. 30 seconds should be enough even when the system is under heavy load, but still will protect your updater from hanging forever. (In case UpdateDll returns FALSE, be sure to present a meaningful error message to your user, stating the name of offending DLL.)

    If you are messing with COM, a call to CoFreeUnusedLibraries before quitting might also be helpful. (http://msdn.microsoft.com/en-us/library/ms679712.aspx) Frankly I don't know if COM might hold on to DLLs even after your process exits, but better be safe.

    Bottom line is that there's a lot of strangeness in Win32 API. You don't have to deal with every case as long as you can find an acceptable solution. Obviously Sleep(100) might break, but a 30-second polling loops seems acceptable to me.