[net.unix-wizards] Writing on shared texts

dave@onfcanim.UUCP (Dave Martindale) (10/27/86)

In article <8545@sun.uucp> guy@sun.uucp (Guy Harris) writes:
>> Waitaminnit... at least on SysV, it is not possible to overwrite, or
>> remove the last link to, any executable file which is currently being
>> run.
>
>There are better reasons for the former restriction.  In an unpaged system,
>if you wrote to the file the change would not necessarily be reflected in
>the copy in main memory or on the swap device; as such, until those copies
>lost their last reference and disappeared, processes trying to execute that
>file would get a copy of the old text and a copy of the new data, which
>would be very confusing.

This is a good reason for not letting people write on shared texts with
the current implementation of the text code, but not necessarily a reason
to avoid fixing the implementation.

In a non-paged system, all that is necessary to allow writes to a shared-text
inode is to "detach" the already-running texts from it.  To do this, just
zero the inode pointer in the text table, decrement the reference count
in the inode, and go on your way.  The write to the inode can proceed;
anyone trying to exec the file while it is being written gets the usual
error, but once the file is no longer open for write it can again be
exec'ed.  The old text table entry will never be used by a new exec,
since it is no longer associated with the file's inode.

The still-executing copies of the old binary are not bothered by any of
this, as a complete copy of the executable is already either in memory
or on the swap device, and the text structure contains all info needed
to keep track of it.  The only difference is that when the last instance
of the old program exits, the code cleaning up the text table entry must
be careful to avoid doing an iput on the text inode if the pointer has
already been zeroed.

(I may have forgotten a detail or two, but the approach is sound - it
was implemented years ago under V7 at Waterloo).

In the case of a system that doesn't load the entire binary at once
(e.g. demand paging), it is much messier.  There is still no problem
in providing a clean copy of the new code for new execs, contrary to
what Guy suggests - just "detach" the text structure as before.

The problem comes in providing pages to the still-executing "old" copies
of the program from a file that no longer exists in the state it was
in when execution began.  To solve this, the "detach" operation would
have to arrange to copy every page of the original file that had not
already been page-faulted into memory from the file system into the
swap device.  This could be very expensive for a large binary, and
a pain to implement since you have to change page tables while you
do it.  Thus the whole thing is probably not worth doing on a system
that does demand paging from the a.out.

guy@sun.UUCP (10/27/86)

> To do this, just zero the inode pointer in the text table,

After having made *damn* sure you've caught all the code that assumes that
"x_iptr" is never null for a valid text table entry, and changed "xalloc"
not to use a null "x_iptr" as an indication of a free text table entry.
(You definitely have to do this with a non-paging S5R2; as I remember, that
code hadn't changed much since V7.)

> In the case of a system that doesn't load the entire binary at once
> (e.g. demand paging), it is much messier.  There is still no problem
> in providing a clean copy of the new code for new execs, contrary to
> what Guy suggests - just "detach" the text structure as before.

Gee, I wasn't aware that I suggested that you can't do it even with the
changes you mention.  My point was that *with the V7/4BSD/unpaged S5R2
implementation* there is a reason for forbidding writes to active shared
text files.  Another possibility is to do what's done with NFS and kill the
process if it tries to fetch a page from the file and the file has been
written since the last time you looked at it.
-- 
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com (or guy@sun.arpa)