6

When a executable file is run in a process, if the executable file is overwritten or deleted and then recreated by reinstallation, will the process rerun the new executable file?

Does the answer to the question depend on

  • whether the executable is run as a service/daemon in the process or not?

  • the operation system, e.g. Linux, Unix, ...?

  • whether the reinstallation is from an installer file (e.g. deb file on Ubuntu, msi on Windows) or from building its source code?

Here are some examples:

  • In Ubuntu, when a process runs an executable file, and when I overwrite the executable file, by manually reinstallation via configure, make, and make install on its source code, the process still continues to run the original executable file, instead of the new executable file.

  • I heard that in Windwos 10, when a process runs an executable file as a service, if we reinstall the executable file via its msi installer file, then the service process will restart to run the new executable file. Is it the same or similar case for installation from .deb files on Ubuntu or Debian?

Thanks.

1

3 Answers 3

7

It depends on the kernel and on the type of executable. It doesn't depend on how the executable was started or installed.

On Linux:

  • For native executables (i.e. binaries containing machine code, executed directly by the kernel), an executable cannot be modified while it's running.

    $ cp /bin/sleep .
    $ ./sleep 999999 &
    $ echo >sleep
    sh: 1: cannot create sleep: Text file busy
    

    It is possible to remove the executable (i.e. unlink it) and create a new one at the same path. Like any other case where a file is removed while it's still open, removing the executable doesn't affect the running process, and doesn't actually remove it from the disk until the file is no longer in use, i.e. until all running instances of the program exit.

  • For scripts (beginning with #!), the script file can be modified while the program is running. Whether that affects the program depends on how the interpreter reads the script. If it reads the whole script into its own memory before starting to execute then the execution won't be affected. If the interpreter reads the script on demand then the execution may be affected; some implementations of sh do that.

Many other Unix systems behave this way, but not all. IIRC older versions of Solaris allow modifying a native executable, which generally causes it to crash. A few Unix variants, including HP/UX, don't even allow removing a native executable that's currently running.

Most software installation programs take care to remove an existing executable before putting a new one in place, as opposed to overwriting the existing binary. E.g. do

rm /bin/target
cp target /bin

rather than just cp target /bin. The install shell command does things this way. This is not ideal though, because if someone tries to execute /bin/target while the cp process is running, they'll get a corrupt program. It's better to copy the file to a temporary name and then rename it to the final name. Renaming a file (i.e. moving it inside the same directory, or more generally moving it inside the same filesystem) removes the prior target file if one exists. This is how dpkg works, for example.

cp target /bin/target.tmp
mv /bin/target.tmp /bin/target
3

You can try it yourself:

$ cp /usr/bin/sleep /tmp/sleep
$ /tmp/sleep 20 &
$ truncate -s 1 /tmp/sleep
truncate: cannot open '/tmp/sleep' for writing: Text file busy

The system does not let you change a running binary. However, you can unlink the file and change it:

$ /tmp/sleep 20 &
$ rm /tmp/sleep
$ cp /usr/bin/ls /tmp/sleep
$ [2]-  Done                    /tmp/sleep 20

Note that for shell scripts, the kernel does not protect the script, as the binary that is busy is /bin/bash, for example. You must not overwrite the shell script file, but you can remove it and replace it with a new one.

As for the installation of updated packages, it depends on the packager as to whether a running daemon will be restarted or not. I don't know if there is a convention, but I looked at some example rpm scriptlets on my Fedora system and they seem to restart on update. For example,

$ rpm --scripts -qf /usr/sbin/xinetd 
...
postuninstall scriptlet (using /bin/sh):
...
if [ $1 -ge 1 ] ; then 
    # Package upgrade, not uninstall 
    systemctl try-restart xinetd.service >/dev/null 2>&1 || : 
fi

An rpm -U upgrade of a package will run the new pre- and post- install scriptlets, then the old pre- and post- uninstall scriptlets. As seen above, the postuninstall will do a restart of the systemd service.


From the comments, check out also this answer on shared libraries, and note how changing interpreted scripts depends very much on how the interpreter buffers or rereads the file, or recompiles it to a new file on the fly.

6
  • would this "non protection" of a script apply to other processes which fork and exec an interpreter which then loads a script, e.g. perl, php, python etc? Mar 24, 2017 at 7:48
  • Try that on an operating system that doesn't lock an executable file or shared object while it's mapped into a running process... Mar 24, 2017 at 8:08
  • It could apply to other interpreters, though some, like python and perl will compile the source into an intermediary form and work with that copy, so you can safely change the source file.
    – meuh
    Mar 24, 2017 at 8:28
  • Good point on scripts. Though the interpreter's read buffer might save at least parts of the script.
    – ilkkachu
    Mar 24, 2017 at 10:49
  • 1
    I had to try: With a big script containing a simple loop, I straced both bash and dash (on Debian), and didn't see them ever getting back to reading the beginning of the script file. Changing the ending of the script before it had been executed did update what was ran, though.
    – ilkkachu
    Mar 24, 2017 at 11:04
1

Will overwriting to an executable file affect a process which is running the original executable file?

usually no, my understanding is that when the kernel fork and execs the new process the executable (which contains a program) is read and loaded into memory.
The underlying file is usually then no longer needed, at least until the next time the file is read for another process.
This is why you need to restart your computer after an update has replaced the underlying file for a system program or library - you can't "affect the running process" (i.e. replace) with a new version that was read from an updated file.
The only way to get the new, updated functionality is to stop the running process and reload it from the new file, but in the case of system programs or the kernel itself, the program can't be shutdown, like you could for example with a browser. And so the entire system has to be brought down in order to read the new - updated - file.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .