Anthony Stone wrote:
> > Aleksandar Donev wrote:
> >
> > > Sorry I forgot to say this important information: I am using the Intel
> > > compiler on Linux x86_64 (I assume in the end the actual linking is done by
> > > ld). I tested and recompiling an executable (even after changing it so the
> > > size of the executable changes) keeps the same inode (Linux's internal file
> > > id as obtained via "ls -i"), so it does seem like the executable is
> > > overwritten in-place. I would have still expected the OS to be wise enough to
> > > protect running jobs from seing any changes but it doesn't seem that way.
> > > Thanks,
> > > Aleks
>
> If the executable is already running and you want to recompile a new
> executable at the same path, then just rename the existing executable:
> mv prog.exe prog.exe.save
> This merely changes the directory entry and doesn't interfere with the
> running job, but the new executable will be written to a new prog.exe.
> Once any running jobs have finished you can delete prog.exe.save.
>
>
> Anthony
I haven't tested this, but I think that on Unix and Unix-like systems,
you can skip the renaming and waiting until running jobs to complete and
simply delete prog.exe before generating a new version of it.
[Exception: if there are scripts running or waiting to run that are not
now running prog.exe but that are expected to do so eventually, you may
wish to use some kind of renaming scheme to minimize the window of time
when prog.exe is not a complete executable. Exactly what kind of
renaming scheme depends on whether it is important that those pending
scripts run the existing prog.exe or the new prog.exe can be
substituted, but in neither of those cases is the scheme described by
Anthony likely to be good enough, because it leaves prog.exe unusable
during the entire period of generating a new prog.exe.]
On many non-Unix systems, if you delete a data file while a running
program is reading it, the file is really deleted, and the running
program dies an untimely death, but under Unix and Unix-like systems,
all that is immediately deleted is the connection between the file name
and the actual file (the i-node and the disk space attached to it), and
the resources used by the actual file are not reclaimed by the operating
system until it is neither connected to a file name nor any running
program. Although I have not tested it, I expect that the latter
systems treat the executable file in an analogous manner. (Can any Unix
gurus confirm or deny this?)
On the other hand, many of those non-Unix systems support mandatory file
locking, such that (by default) a file cannot be modified while it is
being read (or read while it is being modified), but Unix and Unix-like
systems provide only a kind of voluntary file locking, which allows
cooperating programs to emulate such exclusion, but which does nothing
to prevent a non-cooperating program from doing whatever it wants with a
file, regardless of the locks held by other programs.
Thus, whether we are talking about data files or executable files, Unix
and Unix-like systems provide protection against such files going away
while they are being actively used, but provide no mandatory protection
against changes to those files. This leads to the somewhat surprising
conclusion that one of the best ways to protect a file against changing
while a program is running is to "delete" the file once it has been
connect to the running program.
Why, you may ask, doesn't ld do such a deletion by default? Although
there are many cases where this would be helpful, there are also a few
cases where it would break things (e.g., if multiple names are
associated with the same i-node). Rather than to try to read the
programmer's mind about what is needed in a particular case, the
traditional Unix approach is a provide tools that behave in a consistent
fashion and make it the programmer's responsibility to use those tools
in a manner appropriate to what the programmer wants to accomplish. As
more and more Unix users come from using more protective systems ("Are
you sure you want to <fill in the blank>?"), this tradition is changing,
but ld is among the oldest of Unix utilities, so we should not be
surprised that it does very little to protect the programmer from the
folly of his/her actions.
[One example of the way this tradition is changing is the increasingly
common practice of placing commands in global initialization files that
alias the rm command to do "rm -i". Some programmers may find this to
be at best only a minimally adequate safety provision. After all,
Windows first asks you whether you really want to delete a file, and
then even if you say yes, it puts it into the Recycling Bin just in case
you change your mind later. On the other hand, programmers who started
out in Unix tend to be in the habit of thinking about whether they want
to delete a file _before_ they type return on the rm command and thus
are often annoyed at the necessity of confirming their desire to delete
the file in question. A decade or two ago, most Unix sysadmins seemed
inclined to accommodate the desires of the latter programmers, making it
the users' responsibility to add an alias for rm if they wanted added
protections, but these days such protection tends to be default and it
is the users' responsibility to remove it if they prefer the convenience
of not saying things twice.]
Since I've babbled on extensively with a lot explanatory material,
perhaps I should repeat my original point:
On Unix and Unix-like systems, it should not be necessary to keep track
of whether a running program is making use of an existing executable
before modifying that executable. Simply delete the existing file
before creating the new version and the operating system will determine
whether (and for how long) to retain the old version of the file to
support existing executions. [I believe this assertion to be true, but
I have not tested it.]
-Kurt
|