[Hackage] #291: cabal-install cannot re-install itself on windows
#291: cabal-install cannot re-install itself on windows ---------------------------------+------------------------------------------ Reporter: duncan | Owner: Type: defect | Status: new Priority: normal | Milestone: Component: cabal-install tool | Version: 1.2.3.0 Severity: normal | Keywords: Difficulty: normal | Ghcversion: 6.8.2 Platform: Windows | ---------------------------------+------------------------------------------ It fails when it gets round to actually installing the executable file. This is because in windows more than a little tricky for a program to replace its own executable file. Trying to overwrite or replace a file that is open by a process fails. It is possible to rename the existing exe file so that the new one can be installed though that still leaves the problem of deleting the old exe file. -- Ticket URL: <http://hackage.haskell.org/trac/hackage/ticket/291> Hackage <http://haskell.org/cabal/> Hackage: Cabal and related projects
#291: cabal-install cannot re-install itself on windows ---------------------------------+------------------------------------------ Reporter: duncan | Owner: Type: defect | Status: new Priority: normal | Milestone: Component: cabal-install tool | Version: 1.2.3.0 Severity: normal | Resolution: Keywords: | Difficulty: normal Ghcversion: 6.8.2 | Platform: Windows ---------------------------------+------------------------------------------ Comment (by guest): http://msdn.microsoft.com/en-us/library/aa365240(VS.85).aspx {{{ MoveFileEx(file_to_delete,NULL,MOVEFILE_DELAY_UNTIL_REBOOT); }}} That will cause the file to be deleted after rebooting. Only works on WinNT kernels, but I don't think we support Win9x anymore (I certainly don't own such a machine!) -- Ticket URL: <http://hackage.haskell.org/trac/hackage/ticket/291#comment:1> Hackage <http://haskell.org/cabal/> Hackage: Cabal and related projects
#291: cabal-install cannot re-install itself on windows ---------------------------------+------------------------------------------ Reporter: duncan | Owner: Type: defect | Status: new Priority: normal | Milestone: Component: cabal-install tool | Version: 1.2.3.0 Severity: normal | Resolution: Keywords: | Difficulty: normal Ghcversion: 6.8.2 | Platform: Windows ---------------------------------+------------------------------------------ Comment (by duncan): http://msdn.microsoft.com/en-us/library/aa363858.aspx Perhaps if we use `CreateFile` to open our own `cabal.exe` file and specify `FILE_FLAG_DELETE_ON_CLOSE` then hopefully that would actually delete the `.exe` file when the process closes (which would be when the last handles are closed). This relies on the `.exe` file itself being opened by the kernel with `FILE_SHARE_DELETE` sharing. This would appear to be the case though since it is possible to rename a `.exe` file while the program is running. See also http://blogs.msdn.com/oldnewthing/archive/2004/06/07/150047.aspx -- Ticket URL: <http://hackage.haskell.org/trac/hackage/ticket/291#comment:2> Hackage <http://haskell.org/cabal/> Hackage: Cabal and related projects
#291: cabal-install cannot re-install itself on windows ---------------------------------+------------------------------------------ Reporter: duncan | Owner: Type: defect | Status: new Priority: normal | Milestone: Component: cabal-install tool | Version: 1.2.3.0 Severity: normal | Resolution: Keywords: | Difficulty: normal Ghcversion: 6.8.2 | Platform: Windows ---------------------------------+------------------------------------------ Comment (by duncan): See http://www.catch22.net/tuts/selfdel.asp for a menu of cunning trickery. Apparently one cannot open an .exe file with `FILE_FLAG_DELETE_ON_CLOSE` however one can execute an .exe file which is already open with `FILE_FLAG_DELETE_ON_CLOSE`. This is the basis of one of the tricks: {{{ [ Current process ] 1. Create a new file with FILE_FLAG_DELETE_ON_CLOSE. 2. Copy the current executable's content into the new file. 3. Create a new process with the duplicate executable: 4. Pass the current executable's full path and PID in the call to CreateFile. 5. Sleep for a short time to give the new process time to start. 6. Close the new file. 7. Exit current process. [ Duplicate process ] 8. Wait for the process specified on command-line to die. 9. Delete file specified on command-line. 10. Exit duplicate process. }}} A problem with implementing this one is getting the synchronisation right. Waiting for the new process to start requires synchronisation. We could do it by waiting for some time and hoping. Doing it properly needs some kind of cross-process lock like a mutex or something hacky like using a file as a lock. Waiting for the old process to die can be done, though not easily. The portable `System.Process` lets us wait for a process, but converting a pid into a ProcessHandle would be tricky (internally the types are incompatible, `type CPid = Word32` vs `type HANDLE = Ptr ()`). It might be more appealing to just leave the old file in place and delete it next time round. -- Ticket URL: <http://hackage.haskell.org/trac/hackage/ticket/291#comment:3> Hackage <http://haskell.org/cabal/> Hackage: Cabal and related projects
#291: cabal-install cannot re-install itself on windows ---------------------------------+------------------------------------------ Reporter: duncan | Owner: Type: defect | Status: new Priority: normal | Milestone: Cabal-1.4 Component: cabal-install tool | Version: HEAD Severity: normal | Resolution: Keywords: | Difficulty: normal Ghcversion: 6.8.2 | Platform: Windows ---------------------------------+------------------------------------------ Changes (by duncan): * version: 1.2.3.0 => HEAD * milestone: => Cabal-1.4 -- Ticket URL: <http://hackage.haskell.org/trac/hackage/ticket/291#comment:4> Hackage <http://haskell.org/cabal/> Hackage: Cabal and related projects
#291: cabal-install cannot re-install itself on windows ---------------------------------+------------------------------------------ Reporter: duncan | Owner: Type: defect | Status: closed Priority: normal | Milestone: Cabal-1.4 Component: cabal-install tool | Version: HEAD Severity: normal | Resolution: fixed Keywords: | Difficulty: normal Ghcversion: 6.8.2 | Platform: Windows ---------------------------------+------------------------------------------ Changes (by duncan): * status: new => closed * resolution: => fixed Comment: {{{ Tue Aug 12 22:51:38 BST 2008 Duncan Coutts <duncan@haskell.org> * Allow cabal-install to re-install itself on Windows This is a fairly heavyweight solution, but then it's quite a nasty problem. What we do is when we notice that we're about to install something in place of our own .exe file, we move our exe file out of the way (but in the same dir). Then after we've installed the new exe we call it and ask it to delete the old file (so we do not litter the bin dir with lots of old versions). That requires synchronising between the old and new programs and for the new program to understand a command to do the syncing and deleting of the old program. Lots of Win32 FFI imports. :-( On the plus side it seems to work and is transparent to the user and the rest of cabal-install. In particular the actual file-installation code (which is burried deep within Cabal) does not need to know about the special case of installing over our own exe file. }}} -- Ticket URL: <http://hackage.haskell.org/trac/hackage/ticket/291#comment:5> Hackage <http://haskell.org/cabal/> Hackage: Cabal and related projects
participants (1)
-
Hackage