[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

savelog can lose data

There is a problem with savelog.  The current log file should not
be moved.  Compressing it removes the original file.  If a
program holds this file open and writes to it after it is removed
then that data is lost.  A lot of data could be lost this way.
This could happen even if the initial backup is not compressed.
The current method assumes that programs periodicly reopen their
log files.  IMHO, that is not a good assumption.

I think a better solution is to copy the data from the current
log file and then truncate it.  There is a race condition with
this approach.  If something is written to the log file between
the copying and the truncating then that data will be lost.  The
time between these two operations should be very small (echo is
built into bash).  Attached is a patch that makes savelog do
this (against slink).

A solution to the race problem would be to lock the log file with
a manditory write lock while doing the copy and the truncate
operations.  Programs writing to the file would block until the
lock is removed.  The problem with this solution is that it
requires the filesystem to mounted with the "mand" option.

Too bad there isn't a way of removing data from the beginning of
a file.  If this capability existed we could: find the size of
the file, copy that much data to a new file, remove that much
data from the start of the log file.



--- /usr/bin/savelog.dist	Fri Apr 23 12:57:43 1999
+++ /usr/bin/savelog	Fri Apr 23 15:37:46 1999
@@ -11,6 +11,9 @@
 # More modifications by Guy Maor <maor@debian.org>:
 #       * cleanup.
 #       * -p (preserve) option
+# Fix by Neil Schemenauer <nascheme@ucalgary.ca>:
+#	* Don't move old log file, truncate it with "echo -n".  The old
+#	  behavior can lose data for programs that keep the log file open.
 # usage: savelog [-m mode] [-u user] [-g group] [-t] [-p] [-c cycle] [-l]
 #                file...
@@ -62,10 +65,10 @@
 # Note: Since the version numbers start with 0, version number <cycle>
 #       is never formed.  The <cycle> count must be at least 2.
-# Bugs: If a process is still writing to the file.0 and savelog
-#	moved it to file.1 and compresses it, data could be lost.
-#	Smail does not have this problem in general because it
-#	restats files often.
+# Bugs: There is a race condition when copying the current log file
+# 	and truncating it. Data will be lost if it is written to the 
+#	log between these two commands. The chance of this happening should 
+#	be very small.
 # common location
 export PATH=$PATH:/sbin:/bin:/usr/sbin:/usr/bin
@@ -213,23 +216,17 @@
 	# create new file if needed
 	if [ -n "$preserve" ]; then
-		cp -p "$filename" "$filename.new"
-		echo -n > "$filename.new"
-		filenew=1
+		[ ! -f "$filename" ] && touch "$filename"
 	elif [ -n "$touch$user$group$mode" ]; then
-		touch "$filename.new"
-		fixfile "$filename.new"
-		filenew=1
+		[ ! -f "$filename" ] && touch "$filename"
+		fixfile "$filename"
-	# link the file into the file.0 holding place
+	# copy current log file and truncate it
 	if [ -f "$filename" ]; then
-		if [ -n "$filenew" ]; then
-			ln -f "$filename" "$newname.0"
-			mv "$filename.new" "$filename"
-		else
-			mv "$filename" "$newname.0"
-		fi
+		# there is a race here
+		cp "$filename" "$newname.0"
+		echo -n > "$filename"
 	[ ! -f "$newname.0" ] && touch "$newname.0"
 	fixfile "$newname.0"

Reply to: