Blob Blame History Raw
diff -up proftpd-1.3.4rc1/src/scoreboard.c.tests proftpd-1.3.4rc1/src/scoreboard.c
--- proftpd-1.3.4rc1/src/scoreboard.c.tests	2010-11-16 15:46:23.000000000 +0000
+++ proftpd-1.3.4rc1/src/scoreboard.c	2010-12-21 22:01:57.177572723 +0000
@@ -392,7 +392,19 @@ void pr_delete_scoreboard(void) {
     }
   }
 
+  if (scoreboard_mutex_fd > -1) {
+    while (close(scoreboard_mutex_fd) < 0) {
+      if (errno == EINTR) {
+        pr_signals_handle();
+        continue;
+      }
+
+      break;
+    }
+  }
+
   scoreboard_fd = -1;
+  scoreboard_mutex_fd = -1;
   scoreboard_opener = 0;
 
   if (*scoreboard_file) {
@@ -406,6 +418,17 @@ void pr_delete_scoreboard(void) {
     (void) unlink(scoreboard_file);
     (void) unlink(scoreboard_mutex);
   }
+
+  if (*scoreboard_mutex) {
+    struct stat st;
+
+    if (stat(scoreboard_mutex, &st) == 0) {
+      pr_log_debug(DEBUG3, "deleting existing scoreboard mutex '%s'",
+        scoreboard_mutex);
+    }
+
+    (void) unlink(scoreboard_mutex);
+  }
 }
 
 const char *pr_get_scoreboard(void) {
diff -up proftpd-1.3.4rc1/tests/api/scoreboard.c.tests proftpd-1.3.4rc1/tests/api/scoreboard.c
--- proftpd-1.3.4rc1/tests/api/scoreboard.c.tests	2010-03-04 17:29:08.000000000 +0000
+++ proftpd-1.3.4rc1/tests/api/scoreboard.c	2010-12-21 21:34:47.427708792 +0000
@@ -131,6 +131,7 @@ END_TEST
 START_TEST (scoreboard_open_close_test) {
   int res;
   const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test",
+    *mutex_path = "/tmp/prt-scoreboard/test.lck",
     *symlink_path = "/tmp/prt-scoreboard/symlink";
 
   res = mkdir(dir, 0775);
@@ -154,12 +155,14 @@ START_TEST (scoreboard_open_close_test) 
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
 
   if (symlink(symlink_path, path) == 0) {
 
     res = pr_open_scoreboard(O_RDWR);
     if (res == 0) {
       (void) unlink(path);
+      (void) unlink(mutex_path);
       (void) unlink(symlink_path);
       (void) rmdir(dir);
 
@@ -170,6 +173,7 @@ START_TEST (scoreboard_open_close_test) 
       int xerrno = errno;
 
       (void) unlink(symlink_path);
+      (void) unlink(mutex_path);
       (void) unlink(path);
       (void) rmdir(dir);
 
@@ -177,12 +181,14 @@ START_TEST (scoreboard_open_close_test) 
     }
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) unlink(symlink_path);
   }
 
   res = pr_open_scoreboard(O_RDONLY);
   if (res == 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly opened scoreboard using O_RDONLY");
@@ -192,6 +198,7 @@ START_TEST (scoreboard_open_close_test) 
     int xerrno = errno;
 
     (void) unlink(symlink_path);
+    (void) unlink(mutex_path);
     (void) unlink(path);
     (void) rmdir(dir);
 
@@ -202,6 +209,7 @@ START_TEST (scoreboard_open_close_test) 
   if (res < 0) {
     int xerrno = errno;
 
+    (void) unlink(mutex_path);
     (void) unlink(path);
     (void) rmdir(dir);
 
@@ -213,6 +221,7 @@ START_TEST (scoreboard_open_close_test) 
 
   res = pr_open_scoreboard(O_RDONLY);
   if (res == 0) {
+    (void) unlink(mutex_path);
     (void) unlink(path);
     (void) rmdir(dir);
 
@@ -222,12 +231,14 @@ START_TEST (scoreboard_open_close_test) 
   if (errno != EINVAL) {
     int xerrno = errno;
 
+    (void) unlink(mutex_path);
     (void) unlink(path);
     (void) rmdir(dir);
 
     fail("Failed to set errno to EINVAL (got %d)", xerrno);
   }
 
+  (void) unlink(mutex_path);
   (void) unlink(path);
   (void) rmdir(dir);
 }
@@ -235,7 +246,8 @@ END_TEST
 
 START_TEST (scoreboard_delete_test) {
   int res;
-  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test";
+  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test",
+    *mutex_path = "/tmp/prt-scoreboard/test.lck";
   struct stat st;
 
   res = mkdir(dir, 0775);
@@ -259,11 +271,13 @@ START_TEST (scoreboard_delete_test) {
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
 
   res = pr_open_scoreboard(O_RDWR);
   if (res < 0) {
     int xerrno = errno;
 
+    (void) unlink(mutex_path);
     (void) unlink(path);
     (void) rmdir(dir);
 
@@ -274,6 +288,7 @@ START_TEST (scoreboard_delete_test) {
   if (res < 0) {
     int xerrno = errno;
 
+    (void) unlink(mutex_path);
     (void) unlink(path);
     (void) rmdir(dir);
 
@@ -285,19 +300,31 @@ START_TEST (scoreboard_delete_test) {
   res = stat(pr_get_scoreboard(), &st);
   if (res == 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly found deleted scoreboard");
   }
 
+  res = stat(pr_get_scoreboard_mutex(), &st);
+  if (res == 0) {
+    (void) unlink(path);
+    (void) unlink(mutex_path);
+    (void) rmdir(dir);
+
+    fail("Unexpectedly found deleted scoreboard mutex");
+  }
+
   (void) unlink(path);
+  (void) unlink(mutex_path);
   (void) rmdir(dir);
 }
 END_TEST
 
 START_TEST (scoreboard_restore_test) {
   int res;
-  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test";
+  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test",
+    *mutex_path = "/tmp/prt-scoreboard/test.lck";
 
   res = mkdir(dir, 0775);
   fail_unless(res == 0, "Failed to create directory '%s': %s", dir,
@@ -320,10 +347,12 @@ START_TEST (scoreboard_restore_test) {
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
 
   res = pr_restore_scoreboard();
   if (res == 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly restored scoreboard");
@@ -333,6 +362,7 @@ START_TEST (scoreboard_restore_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to set errno to EINVAL (got %d)", xerrno);
@@ -343,6 +373,7 @@ START_TEST (scoreboard_restore_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to open scoreboard: %s", strerror(xerrno));
@@ -353,19 +384,22 @@ START_TEST (scoreboard_restore_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to restore scoreboard: %s", strerror(xerrno));
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
   (void) rmdir(dir);
 }
 END_TEST
 
 START_TEST (scoreboard_rewind_test) {
   int res;
-  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test";
+  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test",
+    *mutex_path = "/tmp/prt-scoreboard/test.lck";
 
   res = mkdir(dir, 0775);
   fail_unless(res == 0, "Failed to create directory '%s': %s", dir,
@@ -388,10 +422,12 @@ START_TEST (scoreboard_rewind_test) {
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
 
   res = pr_rewind_scoreboard();
   if (res == 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly rewound scoreboard");
@@ -401,6 +437,7 @@ START_TEST (scoreboard_rewind_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to set errno to EINVAL (got %d)", xerrno);
@@ -411,6 +448,7 @@ START_TEST (scoreboard_rewind_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to open scoreboard: %s", strerror(xerrno));
@@ -421,12 +459,14 @@ START_TEST (scoreboard_rewind_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to rewind scoreboard: %s", strerror(xerrno));
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
   (void) rmdir(dir);
 }
 END_TEST
@@ -434,7 +474,8 @@ END_TEST
 START_TEST (scoreboard_scrub_test) {
   uid_t euid;
   int res;
-  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test";
+  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test",
+    *mutex_path = "/tmp/prt-scoreboard/test.lck";
 
   res = mkdir(dir, 0775);
   fail_unless(res == 0, "Failed to create directory '%s': %s", dir,
@@ -457,10 +498,12 @@ START_TEST (scoreboard_scrub_test) {
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
 
   res = pr_scoreboard_scrub();
   if (res == 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly scrubbed scoreboard");
@@ -472,6 +515,7 @@ START_TEST (scoreboard_scrub_test) {
       int xerrno = errno;
 
       (void) unlink(path);
+      (void) unlink(mutex_path);
       (void) rmdir(dir);
 
       fail("Failed to set errno to EPERM, got %d (euid = %lu)", xerrno,
@@ -483,6 +527,7 @@ START_TEST (scoreboard_scrub_test) {
       int xerrno = errno;
 
       (void) unlink(path);
+      (void) unlink(mutex_path);
       (void) rmdir(dir);
 
       fail("Failed to set errno to ENOENT, got %d (euid = %lu)", xerrno,
@@ -495,6 +540,7 @@ START_TEST (scoreboard_scrub_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to open scoreboard: %s", strerror(xerrno));
@@ -505,19 +551,22 @@ START_TEST (scoreboard_scrub_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to scrub scoreboard: %s", strerror(xerrno));
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
   (void) rmdir(dir);
 }
 END_TEST
 
 START_TEST (scoreboard_get_daemon_pid_test) {
   int res;
-  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test";
+  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test",
+    *mutex_path = "/tmp/prt-scoreboard/test.lck";
   pid_t daemon_pid;
 
   res = mkdir(dir, 0775);
@@ -541,12 +590,14 @@ START_TEST (scoreboard_get_daemon_pid_te
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
 
   res = pr_open_scoreboard(O_RDWR);
   if (res < 0) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to open scoreboard: %s", strerror(xerrno));
@@ -555,6 +606,7 @@ START_TEST (scoreboard_get_daemon_pid_te
   daemon_pid = pr_scoreboard_get_daemon_pid();
   if (daemon_pid != getpid()) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Expected %lu, got %lu", (unsigned long) getpid(),
@@ -570,6 +622,7 @@ START_TEST (scoreboard_get_daemon_pid_te
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to open scoreboard: %s", strerror(xerrno));
@@ -578,6 +631,7 @@ START_TEST (scoreboard_get_daemon_pid_te
   daemon_pid = pr_scoreboard_get_daemon_pid();
   if (daemon_pid != 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Expected %lu, got %lu", (unsigned long) 0,
@@ -585,13 +639,15 @@ START_TEST (scoreboard_get_daemon_pid_te
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
   (void) rmdir(dir);
 }
 END_TEST
 
 START_TEST (scoreboard_get_daemon_uptime_test) {
   int res;
-  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test";
+  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test",
+    *mutex_path = "/tmp/prt-scoreboard/test.lck";
   time_t daemon_uptime, now;
 
   res = mkdir(dir, 0775);
@@ -615,12 +671,14 @@ START_TEST (scoreboard_get_daemon_uptime
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
 
   res = pr_open_scoreboard(O_RDWR);
   if (res < 0) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to open scoreboard: %s", strerror(xerrno));
@@ -631,6 +689,7 @@ START_TEST (scoreboard_get_daemon_uptime
 
   if (daemon_uptime > now) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Expected %lu, got %lu", (unsigned long) now,
@@ -646,6 +705,7 @@ START_TEST (scoreboard_get_daemon_uptime
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to open scoreboard: %s", strerror(xerrno));
@@ -654,6 +714,7 @@ START_TEST (scoreboard_get_daemon_uptime
   daemon_uptime = pr_scoreboard_get_daemon_uptime();
   if (daemon_uptime != 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Expected %lu, got %lu", (unsigned long) 0,
@@ -661,13 +722,15 @@ START_TEST (scoreboard_get_daemon_uptime
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
   (void) rmdir(dir);
 }
 END_TEST
 
 START_TEST (scoreboard_entry_add_test) {
   int res;
-  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test";
+  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test",
+    *mutex_path = "/tmp/prt-scoreboard/test.lck";
 
   res = mkdir(dir, 0775);
   fail_unless(res == 0, "Failed to create directory '%s': %s", dir,
@@ -690,10 +753,12 @@ START_TEST (scoreboard_entry_add_test) {
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
 
   res = pr_scoreboard_entry_add();
   if (res == 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly added entry to scoreboard");
@@ -703,6 +768,7 @@ START_TEST (scoreboard_entry_add_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to set errno to EINVAL (got %d)", xerrno);
@@ -713,6 +779,7 @@ START_TEST (scoreboard_entry_add_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to open scoreboard: %s", strerror(xerrno));
@@ -723,6 +790,7 @@ START_TEST (scoreboard_entry_add_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to add entry to scoreboard: %s", strerror(xerrno));
@@ -731,6 +799,7 @@ START_TEST (scoreboard_entry_add_test) {
   res = pr_scoreboard_entry_add();
   if (res == 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly added entry to scoreboard");
@@ -740,19 +809,22 @@ START_TEST (scoreboard_entry_add_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to set errno to EPERM (got %d)", xerrno);
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
   (void) rmdir(dir);
 }
 END_TEST
 
 START_TEST (scoreboard_entry_del_test) {
   int res;
-  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test";
+  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test",
+    *mutex_path = "/tmp/prt-scoreboard/test.lck";
 
   res = mkdir(dir, 0775);
   fail_unless(res == 0, "Failed to create directory '%s': %s", dir,
@@ -775,10 +847,12 @@ START_TEST (scoreboard_entry_del_test) {
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
 
   res = pr_scoreboard_entry_del(FALSE);
   if (res == 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly deleted entry from scoreboard");
@@ -788,6 +862,7 @@ START_TEST (scoreboard_entry_del_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to set errno to EINVAL (got %d)", xerrno);
@@ -798,6 +873,7 @@ START_TEST (scoreboard_entry_del_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to open scoreboard: %s", strerror(xerrno));
@@ -806,6 +882,7 @@ START_TEST (scoreboard_entry_del_test) {
   res = pr_scoreboard_entry_del(FALSE);
   if (res == 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly deleted entry from scoreboard");
@@ -815,6 +892,7 @@ START_TEST (scoreboard_entry_del_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to set errno to ENOENT (got %d)", xerrno);
@@ -825,6 +903,7 @@ START_TEST (scoreboard_entry_del_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to add entry to scoreboard: %s", strerror(xerrno));
@@ -835,6 +914,7 @@ START_TEST (scoreboard_entry_del_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to delete entry from scoreboard: %s", strerror(xerrno));
@@ -843,6 +923,7 @@ START_TEST (scoreboard_entry_del_test) {
   res = pr_scoreboard_entry_del(FALSE);
   if (res == 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly deleted entry from scoreboard");
@@ -852,19 +933,22 @@ START_TEST (scoreboard_entry_del_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to set errno to ENOENT (got %d)", xerrno);
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
   (void) rmdir(dir);
 }
 END_TEST
 
 START_TEST (scoreboard_entry_read_test) {
   int res;
-  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test";
+  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test",
+    *mutex_path = "/tmp/prt-scoreboard/test.lck";
   pr_scoreboard_entry_t *score;
 
   res = mkdir(dir, 0775);
@@ -888,10 +972,12 @@ START_TEST (scoreboard_entry_read_test) 
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
 
   score = pr_scoreboard_entry_read();
   if (score != NULL) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly read scoreboard entry");
@@ -901,6 +987,7 @@ START_TEST (scoreboard_entry_read_test) 
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to set errno to EINVAL (got %d)", xerrno);
@@ -911,6 +998,7 @@ START_TEST (scoreboard_entry_read_test) 
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to open scoreboard: %s", strerror(xerrno));
@@ -920,6 +1008,7 @@ START_TEST (scoreboard_entry_read_test) 
   score = pr_scoreboard_entry_read();
   if (score != NULL) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly read scoreboard entry");
@@ -930,6 +1019,7 @@ START_TEST (scoreboard_entry_read_test) 
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to add entry to scoreboard: %s", strerror(xerrno));
@@ -940,6 +1030,7 @@ START_TEST (scoreboard_entry_read_test) 
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to read scoreboard entry: %s", strerror(xerrno));
@@ -947,6 +1038,7 @@ START_TEST (scoreboard_entry_read_test) 
 
   if (score->sce_pid != getpid()) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to read expected scoreboard entry (expected PID %lu, got %lu)",
@@ -956,19 +1048,22 @@ START_TEST (scoreboard_entry_read_test) 
   score = pr_scoreboard_entry_read();
   if (score != NULL) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly read scoreboard entry");
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
   (void) rmdir(dir);
 }
 END_TEST
 
 START_TEST (scoreboard_entry_get_test) {
   int res;
-  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test";
+  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test",
+    *mutex_path = "/tmp/prt-scoreboard/test.lck";
   const char *val;
 
   res = mkdir(dir, 0775);
@@ -992,10 +1087,12 @@ START_TEST (scoreboard_entry_get_test) {
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
 
   val = pr_scoreboard_entry_get(-1);
   if (val != NULL) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly read value from scoreboard entry");
@@ -1005,6 +1102,7 @@ START_TEST (scoreboard_entry_get_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to set errno to EINVAL (got %d)", xerrno);
@@ -1015,6 +1113,7 @@ START_TEST (scoreboard_entry_get_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to open scoreboard: %s", strerror(xerrno));
@@ -1023,6 +1122,7 @@ START_TEST (scoreboard_entry_get_test) {
   val = pr_scoreboard_entry_get(-1);
   if (val != NULL) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly read value from scoreboard entry");
@@ -1032,6 +1132,7 @@ START_TEST (scoreboard_entry_get_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to set errno to EPERM (got %d)", xerrno);
@@ -1042,6 +1143,7 @@ START_TEST (scoreboard_entry_get_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to add entry to scoreboard: %s", strerror(xerrno));
@@ -1050,6 +1152,7 @@ START_TEST (scoreboard_entry_get_test) {
   val = pr_scoreboard_entry_get(-1);
   if (val != NULL) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly read value from scoreboard entry");
@@ -1059,12 +1162,14 @@ START_TEST (scoreboard_entry_get_test) {
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to set errno to ENOENT (got %d)", xerrno);
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
   (void) rmdir(dir);
 }
 END_TEST
@@ -1072,7 +1177,8 @@ END_TEST
 START_TEST (scoreboard_entry_update_test) {
   int res;
   const char *val;
-  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test";
+  const char *dir = "/tmp/prt-scoreboard/", *path = "/tmp/prt-scoreboard/test",
+    *mutex_path = "/tmp/prt-scoreboard/test.lck";
   pid_t pid = getpid();
 
   res = mkdir(dir, 0775);
@@ -1096,10 +1202,12 @@ START_TEST (scoreboard_entry_update_test
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
 
   res = pr_scoreboard_entry_update(pid, 0);
   if (res == 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly updated scoreboard entry");
@@ -1109,6 +1217,7 @@ START_TEST (scoreboard_entry_update_test
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to set errno to EINVAL (got %d)", xerrno);
@@ -1119,6 +1228,7 @@ START_TEST (scoreboard_entry_update_test
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to open scoreboard: %s", strerror(xerrno));
@@ -1127,6 +1237,7 @@ START_TEST (scoreboard_entry_update_test
   res = pr_scoreboard_entry_update(pid, 0);
   if (res == 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly updated scoreboard entry");
@@ -1136,6 +1247,7 @@ START_TEST (scoreboard_entry_update_test
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to set errno to EPERM (got %d)", xerrno);
@@ -1146,6 +1258,7 @@ START_TEST (scoreboard_entry_update_test
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to add entry to scoreboard: %s", strerror(xerrno));
@@ -1154,6 +1267,7 @@ START_TEST (scoreboard_entry_update_test
   res = pr_scoreboard_entry_update(pid, -1);
   if (res == 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Unexpectedly updated scoreboard entry");
@@ -1163,6 +1277,7 @@ START_TEST (scoreboard_entry_update_test
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to set errno to ENOENT (got %d)", xerrno);
@@ -1174,6 +1289,7 @@ START_TEST (scoreboard_entry_update_test
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to update PR_SCORE_CWD: %s", strerror(xerrno));
@@ -1184,6 +1300,7 @@ START_TEST (scoreboard_entry_update_test
     int xerrno = errno;
 
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Failed to get entry PR_SCORE_CWD: %s", strerror(xerrno));
@@ -1191,12 +1308,14 @@ START_TEST (scoreboard_entry_update_test
 
   if (strcmp(val, "cwd") != 0) {
     (void) unlink(path);
+    (void) unlink(mutex_path);
     (void) rmdir(dir);
 
     fail("Expected '%s', got '%s'", "cwd", val);
   }
 
   (void) unlink(path);
+  (void) unlink(mutex_path);
   (void) rmdir(dir);
 }
 END_TEST
diff -up proftpd-1.3.4rc1/tests/api/stubs.c.tests proftpd-1.3.4rc1/tests/api/stubs.c
--- proftpd-1.3.4rc1/tests/api/stubs.c.tests	2008-10-06 19:16:50.000000000 +0100
+++ proftpd-1.3.4rc1/tests/api/stubs.c	2010-12-21 21:34:47.428708819 +0000
@@ -34,6 +34,10 @@ server_rec *main_server = NULL;
 module *static_modules[] = { NULL };
 module *loaded_modules = NULL;
 
+int pr_ctrls_unregister(module *m, const char *action) {
+  return 0;
+}
+
 void pr_log_debug(int level, const char *fmt, ...) {
 }
 
diff -up proftpd-1.3.4rc1/tests/api/pool.c.tests proftpd-1.3.4rc1/tests/api/pool.c
--- proftpd-1.3.4rc1/tests/api/pool.c.tests	2009-01-30 00:14:16.000000000 +0000
+++ proftpd-1.3.4rc1/tests/api/pool.c	2010-12-23 13:32:48.022565092 +0000
@@ -116,7 +116,7 @@
   fail_unless(v == NULL, "Allocated %u-len memory", sz);
 
   sz = 1;
-  v = palloc(p, sz);
+  v = pcalloc(p, sz);
   fail_if(v == NULL, "Failed to allocate %u-len memory", sz);
   for (i = 0; i < sz; i++) {
     fail_unless(v[i] == 0, "Allocated non-zero memory at position %u", i);
diff -up proftpd-1.3.4rc1/tests/api/timers.c.tests proftpd-1.3.4rc1/tests/api/timers.c
--- proftpd-1.3.4rc1/tests/api/timers.c.tests	2010-08-11 15:56:36.000000000 +0100
+++ proftpd-1.3.4rc1/tests/api/timers.c	2010-12-24 11:03:17.625550991 +0000
@@ -121,7 +121,7 @@
   timers_handle_signals();
 
   ok = 2;
-  fail_unless(timer_triggered_count == ok,
+  fail_unless(timer_triggered_count == ok || timer_triggered_count == ok + 1,
     "Timer failed to fire (expected count %u, got %u)", ok,
     timer_triggered_count);
 
@@ -129,7 +129,7 @@
   timers_handle_signals();
 
   ok = 3;
-  fail_unless(timer_triggered_count == ok,
+  fail_unless(timer_triggered_count == ok || timer_triggered_count == ok + 1,
     "Timer failed to fire (expected count %u, got %u)", ok,
     timer_triggered_count);
 }