views:

238

answers:

8

What happens if I recompile an executable while it's running? Does the operating system read all of the executable's contents into memory when it starts running it, so it will never read the new executable file? Or will it read sections of the new executable file thinking it hasn't changed, leading to possibly undefined behaviour?

What if I have a script running which repeatedly invokes an executable in a loop, and I recompile the executable while the script is running. Is it guaranteed that future iterations of the loop will invoke the new executable, and only the result of the invocation that was in progress when the switch was made might be corrupted?

My OS is Linux, but I'm also curious about what happens on Windows.

+4  A: 

It depends.

If the OS read the whole of the executable into memory and doesn't refer back to the disk image then yes you can recompile it while it was "in use".

In practice this doesn't always happen. If the OS keeps a file handle open (like Windows does) on the executable this will prevent the file being deleted and/or overwritten.

With Linux/Unix it is possible to overwrite a file that's "in use". See David Thornley's answer for a detailed explanation.

ChrisF
Windows will prevent the file from being deleted. Linux will let you "delete" the file from a directory, but the file won't actually be removed until the program closes.
Karmastan
On Linux it will *not* prevent the file from being deleted and overwritten from most perspectives, but a process that has an open file handle prevents the disk space from being freed/reused until all handles are closed, and that process can still access the original unchanged file. This is entirely different under Windows.
Stephen P
@Karmastan, @Stephen - which is why I said "it depends".
ChrisF
@ChrisF: which is why we clarified your statement :)
Karmastan
@Karmastan- touché
ChrisF
@ChrisF: You said that it depends on whether we are talking on theory or practice. That is, you stated that UNIX exists only theoretically;)
el.pescado
@el.pescado - better?
ChrisF
@ChrisF: better, but still not perfect. See Stephen P's comment and David Thornley's answer how UNIX handles deleted files.
el.pescado
A: 

I would imagine it wouldn't let you replace the file, since windows locked it down while it was in use.

Eclyps19
A: 

It depends. From what I've experienced, on Linux you can still be running a program if you delete it (and it's not too large). But I don't think that's defined behavior.

As far as the loop goes, depending on how you're invoking the executable, you will likely end out crashing your script when it goes to execute a program that's only halfway been written.

Wayne Werner
A: 

In Windows you can't if the executable is still running, the file will be locked. If the exe isn't actually running, the new runs should pick up the new one, depending on how your script is coded among other things.

I don't know about Linux.

BioBuckyBall
A: 

The Executable might be loaded completely into the memory on startup, however if it's large enough, and running long enough, the OS might decide to swap out some unused parts of it.

Since the OS assumes that the program's file is still there, there is no reason to actually write these memory blocks into the swap file. So they are simply invalidated and reused. If the program needs these pages again, the OS loads them from the executable file.

In Windows this actually happens automagically, since a loaded module is a memory mapped file. That also means that the file is locked during it's execution, and you will not be able to overwrite it easily.

Not sure about Linux, but IIRC it does the swapping the same way.

Fozi
+10  A: 

Since this is a conventional compiler, that writes out an executable file, let's follow it in Linux.

The first thing to know is that a Linux filename doesn't directly refer to the file, but rather to a directory entry, which is independent of the filename. A file doesn't actually need to have a filename, but if it doesn't it will be difficult to refer to it.

If a process is using a file, and you replace or delete it, the process will continue using that file through its directory entry. Any new process using the file, or looking it up, will get the new version (if you replaced it) or fail to find it (if you deleted it). Once all the processes are through with the old file, it will be deleted from the file system.

Therefore, if you recompile and create a new executable of the same name, you won't affect the running process. It will continue to use the old executable. Any new process that tries to open the file will get the new one. If you've got system("foo"); in a loop, each time it executes it it will see what the filename foo means right then.

Windows handles files differently. In general, if there's a process using a file, the file is locked and may not be deleted or replaced.

David Thornley
Interesting - that gives me some good insight into how Linux handles files.
HighCommander4
[Linux] It depends on how you "replace" a file as to whether it will work or not. You cannot open an in-use executable for writing.
camh
What if, halfway through the linker's output of the .exe file, I attempt to run it? Will it attempt to start a half-written executable?
Thanatos
@Thanatos: Typically, files will be written out to a temporary name, and then `mv`ed to the correct path and name. This means you're going to get either the new or the old version. If not, and it's writing it out in place, I doubt you'll be able to execute the program. Under normal circumstances, you won't be able to start a half-written executable.
David Thornley
+1  A: 

In Windows you can't delete a locked file but what most people don't know is that you can move or rename a running exe.

So you could

  • move the old exe to a temp directory on the same drive
  • schedule it for deletion on the next reboot: MoveFileEx(name, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  • move a new exe in its place.

The old program will keep running but new processes will use the new file.

chris
A: 

Under Linux, executables are demand paged into memory as needed. The executable on disk becomes the backing store for the application. This means you cannot modify the executable on disk or you will affect a running application. If you try to open(2) an in-use executable for writing, you will get an ETXTBSY (Text file busy) error (check the man page for open(2)).

As many others have said, you can remove the file from the filesystem (unlink(2)) and the kernel will maintain a reference to it and not delete it from disk until there are no more references (when the process exits, it will release its reference to the file). This means you can effectively "overwrite" an in-use executable by first removing it and then creating a new file with the same name as the old file.

So, it comes down to how the compiler creates the executable when "overwriting" an existing file. If it just opens the file for writing and truncates it (O_WRONLY|O_CREAT|O_TRUNC), the it will fail with an ETXTBSY error. If it first removes the existing output file and creates a new one, it will work without error.

camh