rnews: batch naming and locking

Miquel van Smoorenburg miquels at cistron.nl
Tue Oct 22 12:31:58 UTC 2002



According to Miquel van Smoorenburg:
> The patch is not completely working though. The fixes are correct,
> but the locking still has a race condition.
> This is caused by the *stupid* POSIX fcntl() locking rules.

.. and here is the fix for that. We simply open the spool file
twice, and use one fd for locking only.

--- inn-2.4-20020916/frontends/rnews.c.orig	Wed Sep 18 12:59:05 2002
+++ inn-2.4-20020916/frontends/rnews.c	Tue Oct 22 13:40:39 2002
@@ -593,7 +593,7 @@
     register bool	ok;
     struct stat		Sb;
     char		hostname[10];
-    int			fd;
+    int			fd, lockfd;
     size_t		i;
     char                *badname, *uuhost;
 
@@ -625,8 +625,20 @@
 	    continue;
 	}
 
-	/* Make sure multiple Unspools don't stomp on eachother */
-	if (!inn_lock_file(fd, INN_LOCK_READ, 0)) {
+	/*
+	** Make sure multiple Unspools don't stomp on eachother.
+	** Because of stupid POSIX locking semantics, we need to lock
+	** on a seperate fd. Otherwise, dup()ing and then close()ing
+	** the dup()ed fd removes the lock we're holding (sigh).
+	*/
+	if ((lockfd = open(InputFile, O_RDONLY)) < 0) {
+	    if (errno != ENOENT)
+                syswarn("cannot open %s", InputFile);
+	    close(fd);
+	    continue;
+	}
+	if (!inn_lock_file(lockfd, INN_LOCK_READ, 0)) {
+	    close(lockfd);
 	    close(fd);
 	    continue;
 	}
@@ -657,12 +669,14 @@
 	    if (rename(InputFile, badname) < 0)
                 sysdie("cannot rename %s to %s", InputFile, badname);
 	    (void)close(fd);
+	    (void)close(lockfd);
 	    continue;
 	}
 
 	if (unlink(InputFile) < 0)
             syswarn("cannot remove %s", InputFile);
 	(void)close(fd);
+	(void)close(lockfd);
     }
     (void)closedir(dp);
 


More information about the inn-patches mailing list