BIND 10 master, updated. adca81c006608c1e97b900380ce48834876c2908 [1704] Add ChangeLog entry

BIND 10 source code commits bind10-changes at lists.isc.org
Sun Jun 3 20:55:16 UTC 2012


The branch, master has been updated
       via  adca81c006608c1e97b900380ce48834876c2908 (commit)
       via  ad8d445dd0ba208107eb239405166c5c2070bd8b (commit)
       via  f71a0c646d703351f989c2705e237fa77705c504 (commit)
       via  7987b09972865cf558dbff4489a198162ec8e3c3 (commit)
       via  1c0e6f80265bb516f5f965eea9b0edac781cbdea (commit)
       via  52edf764154ed08161a4683d6b7b7be5a232face (commit)
       via  cc84b0a02de65a71d80fac9b6f15533e9b0c6037 (commit)
       via  f68857bea3699eb23c72ddac04a20aa8f42bd551 (commit)
       via  07851523e66fe1e045e953d505b97e2cf7f499fc (commit)
       via  6306feefed1a1fc462bfff708a47c5fffb351a51 (commit)
       via  8d55fd24318cd72d0a624304dfb7c107813e43cf (commit)
       via  a0bf4ce38c190728f172ee9e2a335248a0ed7a1d (commit)
       via  088760558f2321ea60b393b37fba0a672ce9f943 (commit)
       via  56c895c19be423403c0ddb84f25ea958af9cc371 (commit)
       via  60c3dcef1055d54231708188639056248258e716 (commit)
       via  d6859a67235140aeb14a2224198b85e4d65ed71d (commit)
       via  162e15111002d1e857222eb309018818b637fbad (commit)
       via  1f12f3cd5bc0b3b39545680c4dd772303c62d43f (commit)
       via  3e8b461db077bf467280cec8c6c2a03dd0df0c6c (commit)
       via  949d3d2f07686be8228f3fdb44a756e280dfbd85 (commit)
       via  e04531f57054b71fa83ad6bc8467e31df311d39c (commit)
       via  30987308b9623d0cbd4aa010c14e5238dd09e023 (commit)
       via  6b3132f71b397e4925b80ed1dc1e3cb834be1294 (commit)
       via  865669e98402f25c41f35e3957bdb9190513bf6f (commit)
       via  58c0a8ef0152662b581b7a13fecf92ed0b0021e8 (commit)
       via  8c38fe10458178dee5a0045ae2bfa3da986d6a0c (commit)
       via  e007ac3e1fb0595497757b3590c3023c825965d4 (commit)
       via  fcb63453e3d835fdca05146482d001035cdbd6af (commit)
       via  cd373315919dd5a20440d27d49c3c0e47ebb3f19 (commit)
       via  277be10c905a1b592cc8ddb2ded6f066c619a0f2 (commit)
       via  8eb4eb3e63b8f19155ae8f021436c881d75706c6 (commit)
       via  e72bc121a7f7e4a85f889a6c1c4eec5bafd51325 (commit)
       via  075eef9a1fe8c61c69532ce8b9dc05eda102f08d (commit)
       via  2e95197a4b47847b4ec85e83bdb1fb5edf685cd0 (commit)
       via  7c1277b0a6750ab51611971adf77a9c2740511cc (commit)
       via  994827bfe0a9b77d3bf724768a2403965cb8ad57 (commit)
       via  39ebe9d1fd4d04690162c92ebb640f36fa2586ca (commit)
       via  9227b2de28f57892f5570ca0f30f0f6c651922be (commit)
       via  1d5bd47c50ca03b87972977bb3bdd8d798148698 (commit)
       via  328f8781d99bdf1c78abbee743b85244ac55f6b8 (commit)
       via  16fc37014cf72d8ca5b3f9461504be2c69a37702 (commit)
       via  d575fbaa4083182e8d6602bb042934451ae06c65 (commit)
       via  bd5494fa3a4aded378c5e2167f6c9e1b7eaf2035 (commit)
       via  8b555fcb29378dcb0db476bf8f53804acae8fe77 (commit)
       via  93fb5cab3e4a0752e2471931e171937392c71ae0 (commit)
       via  caa5bb9a9b852631d1548460daef2b93cf48c64c (commit)
       via  227d01775bdb4dab84c97e5858c0812e2aa845c2 (commit)
       via  30198a34b9e464ffa2947955e7dd70a191e39682 (commit)
       via  c0a328b2d94321966d5ebe97dd8f2058d6d76176 (commit)
       via  b45a54e8ccf0c947b7f3979ed1083260c47be453 (commit)
       via  8c455b3a39a588e11a86523056caa9c379b60a67 (commit)
       via  31b153df2003831950bf3fcd6a4da782dc579eb1 (commit)
       via  10b434be10f3fa900760180feb030907484c9b6f (commit)
       via  db2fa0cd177d28c49a9c99aabe44bd9c47c6b78d (commit)
       via  09e8c9e8c55571196fbd297fda46e95400aa0990 (commit)
       via  2bf7dad904d16760987d3a0b27c02bb8a2b50e55 (commit)
       via  876dd74d15bcaa619602bcb60fc769d541923048 (commit)
       via  17f327dc2a155c493dfe265cb6fac7b09a7d8836 (commit)
       via  96391341079418eeb6c3dd6f0da85239d19f1749 (commit)
       via  9427bd4115b59e4498d13dc0a83fc2953b104266 (commit)
       via  588bffd5077a9e6cc741100cdc721b444d80c4ca (commit)
       via  106ec83cb515ddcc84834ba336dc39679377a8fd (commit)
      from  1bf6cdf0b6217de0bfd33116881d8ca252617d13 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit adca81c006608c1e97b900380ce48834876c2908
Author: Mukund Sivaraman <muks at isc.org>
Date:   Mon Jun 4 02:24:59 2012 +0530

    [1704] Add ChangeLog entry

commit ad8d445dd0ba208107eb239405166c5c2070bd8b
Merge: f71a0c6 1bf6cdf
Author: Mukund Sivaraman <muks at isc.org>
Date:   Mon Jun 4 00:41:11 2012 +0530

    Merge branch 'master' into trac1704_2

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                                          |   11 ++
 Makefile.am                                        |    2 +
 configure.ac                                       |    2 +
 src/bin/bind10/bind10_src.py.in                    |   24 +++
 src/bin/bind10/tests/Makefile.am                   |    1 +
 src/bin/bind10/tests/bind10_test.py.in             |   35 ++++
 src/bin/cmdctl/tests/Makefile.am                   |    1 +
 src/bin/dbutil/tests/Makefile.am                   |    1 +
 src/bin/stats/tests/Makefile.am                    |    1 +
 src/lib/log/Makefile.am                            |    1 +
 src/lib/log/logger.cc                              |    7 +
 src/lib/log/logger.h                               |   23 +++
 src/lib/log/logger_impl.cc                         |   35 +++-
 src/lib/log/logger_impl.h                          |   18 ++-
 src/lib/log/logger_manager.cc                      |    8 +
 src/lib/log/logger_unittest_support.cc             |    3 +
 src/lib/log/tests/.gitignore                       |    4 +
 src/lib/log/tests/Makefile.am                      |   17 ++
 .../lib/log/tests/log_test_messages.mes            |   24 ++-
 src/lib/log/tests/logger_example.cc                |   10 +-
 src/lib/log/tests/logger_lock_test.cc              |   64 ++++++++
 src/lib/log/tests/logger_lock_test.sh.in           |   46 ++++++
 src/lib/log/tests/logger_unittest.cc               |   66 ++++++++
 src/lib/log/tests/run_initializer_unittests.cc     |    1 +
 src/lib/log/tests/run_unittests.cc                 |    1 +
 src/lib/python/isc/bind10/tests/Makefile.am        |    1 +
 src/lib/python/isc/config/tests/Makefile.am        |    1 +
 src/lib/python/isc/log/tests/Makefile.am           |    3 +
 src/lib/python/isc/server_common/tests/Makefile.am |    1 +
 src/lib/python/isc/xfrin/tests/Makefile.am         |    1 +
 src/lib/util/Makefile.am                           |    4 +
 src/lib/util/interprocess_sync.h                   |  149 +++++++++++++++++
 src/lib/util/interprocess_sync_file.cc             |  130 +++++++++++++++
 src/lib/util/interprocess_sync_file.h              |   91 +++++++++++
 .../resource.cc => interprocess_sync_null.cc}      |   35 ++--
 src/lib/util/interprocess_sync_null.h              |   64 ++++++++
 src/lib/util/tests/Makefile.am                     |    2 +
 .../util/tests/interprocess_sync_file_unittest.cc  |  169 ++++++++++++++++++++
 .../util/tests/interprocess_sync_null_unittest.cc  |   76 +++++++++
 src/lib/util/tests/run_unittests.cc                |    2 +
 40 files changed, 1103 insertions(+), 32 deletions(-)
 copy tests/system/ixfr/clean_ns.sh => src/lib/log/tests/log_test_messages.mes (55%)
 create mode 100644 src/lib/log/tests/logger_lock_test.cc
 create mode 100755 src/lib/log/tests/logger_lock_test.sh.in
 create mode 100644 src/lib/util/interprocess_sync.h
 create mode 100644 src/lib/util/interprocess_sync_file.cc
 create mode 100644 src/lib/util/interprocess_sync_file.h
 copy src/lib/util/{unittests/resource.cc => interprocess_sync_null.cc} (69%)
 create mode 100644 src/lib/util/interprocess_sync_null.h
 create mode 100644 src/lib/util/tests/interprocess_sync_file_unittest.cc
 create mode 100644 src/lib/util/tests/interprocess_sync_null_unittest.cc

-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index c849b55..ac66f52 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+443.    [func]*		muks
+	The logger now uses a lockfile named `logger_lockfile' that is
+	created in the local state directory to mutually separate
+	individual logging operations from various processes. This is
+	done so that log messages from different processes don't mix
+	together in the middle of lines. The `logger_lockfile` is created
+	with file permission mode 0660. BIND 10's local state directory
+	should be writable and perhaps have g+s mode bit so that the
+	`logger_lockfile` can be opened by a group of processes.
+	(Trac #1704, git ad8d445dd0ba208107eb239405166c5c2070bd8b)
+
 442.	[func]		tomek
 	b10-dhcp4, b10-dhcp6: Both DHCP servers now accept -p parameter
 	that can be used to specify listening port number. This capability
diff --git a/Makefile.am b/Makefile.am
index 54216b6..ccc5524 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -405,3 +405,5 @@ EXTRA_DIST += ext/coroutine/coroutine.h
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = dns++.pc
+
+CLEANFILES = $(abs_top_builddir)/logger_lockfile
diff --git a/configure.ac b/configure.ac
index 6935431..7b8071e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1187,6 +1187,7 @@ AC_OUTPUT([doc/version.ent
            src/lib/log/tests/destination_test.sh
            src/lib/log/tests/init_logger_test.sh
            src/lib/log/tests/local_file_test.sh
+           src/lib/log/tests/logger_lock_test.sh
            src/lib/log/tests/severity_test.sh
            src/lib/log/tests/tempdir.h
            src/lib/util/python/mkpywrapper.py
@@ -1235,6 +1236,7 @@ AC_OUTPUT([doc/version.ent
            chmod +x src/lib/log/tests/destination_test.sh
            chmod +x src/lib/log/tests/init_logger_test.sh
            chmod +x src/lib/log/tests/local_file_test.sh
+           chmod +x src/lib/log/tests/logger_lock_test.sh
            chmod +x src/lib/log/tests/severity_test.sh
            chmod +x src/lib/util/python/mkpywrapper.py
            chmod +x src/lib/util/python/gen_wiredata.py
diff --git a/src/bin/bind10/bind10_src.py.in b/src/bin/bind10/bind10_src.py.in
index 37b845d..08e16c6 100755
--- a/src/bin/bind10/bind10_src.py.in
+++ b/src/bin/bind10/bind10_src.py.in
@@ -64,6 +64,7 @@ import posix
 import copy
 
 from bind10_config import LIBEXECPATH
+import bind10_config
 import isc.cc
 import isc.util.process
 import isc.net.parse
@@ -1122,6 +1123,28 @@ def unlink_pid_file(pid_file):
         if error.errno is not errno.ENOENT:
             raise
 
+def remove_lock_files():
+    """
+    Remove various lock files which were created by code such as in the
+    logger. This function should be called after BIND 10 shutdown.
+    """
+
+    lockfiles = ["logger_lockfile"]
+
+    lpath = bind10_config.DATA_PATH
+    if "B10_FROM_BUILD" in os.environ:
+        lpath = os.environ["B10_FROM_BUILD"]
+    if "B10_FROM_SOURCE_LOCALSTATEDIR" in os.environ:
+        lpath = os.environ["B10_FROM_SOURCE_LOCALSTATEDIR"]
+    if "B10_LOCKFILE_DIR_FROM_BUILD" in os.environ:
+        lpath = os.environ["B10_LOCKFILE_DIR_FROM_BUILD"]
+
+    for f in lockfiles:
+        fname = lpath + '/' + f
+        if os.path.isfile(fname):
+            os.unlink(fname)
+
+    return
 
 def main():
     global options
@@ -1201,6 +1224,7 @@ def main():
     finally:
         # Clean up the filesystem
         unlink_pid_file(options.pid_file)
+        remove_lock_files()
         if boss_of_bind is not None:
             boss_of_bind.remove_socket_srv()
     sys.exit(boss_of_bind.exitcode)
diff --git a/src/bin/bind10/tests/Makefile.am b/src/bin/bind10/tests/Makefile.am
index d54ee56..a5e3fab 100644
--- a/src/bin/bind10/tests/Makefile.am
+++ b/src/bin/bind10/tests/Makefile.am
@@ -23,6 +23,7 @@ endif
 	chmod +x $(abs_builddir)/$$pytest ; \
 	$(LIBRARY_PATH_PLACEHOLDER) \
 	PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_srcdir)/src/bin:$(abs_top_builddir)/src/bin/bind10:$(abs_top_builddir)/src/lib/util/io/.libs \
+	B10_LOCKFILE_DIR_FROM_BUILD=$(abs_top_builddir) \
 	BIND10_MSGQ_SOCKET_FILE=$(abs_top_builddir)/msgq_socket \
 		$(PYCOVERAGE_RUN) $(abs_builddir)/$$pytest || exit ; \
 	done
diff --git a/src/bin/bind10/tests/bind10_test.py.in b/src/bin/bind10/tests/bind10_test.py.in
index 84a9da9..3b80fb5 100644
--- a/src/bin/bind10/tests/bind10_test.py.in
+++ b/src/bin/bind10/tests/bind10_test.py.in
@@ -1463,6 +1463,41 @@ class SocketSrvTest(unittest.TestCase):
         self.assertEqual({}, self.__boss._unix_sockets)
         self.assertTrue(sock.closed)
 
+class TestFunctions(unittest.TestCase):
+    def setUp(self):
+        self.lockfile_testpath = \
+            "@abs_top_builddir@/src/bin/bind10/tests/lockfile_test"
+        self.assertFalse(os.path.exists(self.lockfile_testpath))
+        os.mkdir(self.lockfile_testpath)
+        self.assertTrue(os.path.isdir(self.lockfile_testpath))
+
+    def tearDown(self):
+        os.rmdir(self.lockfile_testpath)
+        self.assertFalse(os.path.isdir(self.lockfile_testpath))
+        os.environ["B10_LOCKFILE_DIR_FROM_BUILD"] = "@abs_top_builddir@"
+
+    def test_remove_lock_files(self):
+        os.environ["B10_LOCKFILE_DIR_FROM_BUILD"] = self.lockfile_testpath
+
+        # create lockfiles for the testcase
+        lockfiles = ["logger_lockfile"]
+        for f in lockfiles:
+            fname = os.environ["B10_LOCKFILE_DIR_FROM_BUILD"] + '/' + f
+            self.assertFalse(os.path.exists(fname))
+            open(fname, "w").close()
+            self.assertTrue(os.path.isfile(fname))
+
+        # first call should clear up all the lockfiles
+        bind10_src.remove_lock_files()
+
+        # check if the lockfiles exist
+        for f in lockfiles:
+            fname = os.environ["B10_LOCKFILE_DIR_FROM_BUILD"] + '/' + f
+            self.assertFalse(os.path.isfile(fname))
+
+        # second call should not assert anyway
+        bind10_src.remove_lock_files()
+
 if __name__ == '__main__':
     # store os.environ for test_unchanged_environment
     original_os_environ = copy.deepcopy(os.environ)
diff --git a/src/bin/cmdctl/tests/Makefile.am b/src/bin/cmdctl/tests/Makefile.am
index 89d89ea..b5b65f6 100644
--- a/src/bin/cmdctl/tests/Makefile.am
+++ b/src/bin/cmdctl/tests/Makefile.am
@@ -22,5 +22,6 @@ endif
 	PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_builddir)/src/bin/cmdctl \
 	CMDCTL_SPEC_PATH=$(abs_top_builddir)/src/bin/cmdctl \
 	CMDCTL_SRC_PATH=$(abs_top_srcdir)/src/bin/cmdctl \
+	B10_LOCKFILE_DIR_FROM_BUILD=$(abs_top_builddir) \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
 	done
diff --git a/src/bin/dbutil/tests/Makefile.am b/src/bin/dbutil/tests/Makefile.am
index c03b262..b4231b3 100644
--- a/src/bin/dbutil/tests/Makefile.am
+++ b/src/bin/dbutil/tests/Makefile.am
@@ -3,4 +3,5 @@ SUBDIRS = . testdata
 # Tests of the update script.
 
 check-local:
+	B10_LOCKFILE_DIR_FROM_BUILD=$(abs_top_builddir) \
 	$(SHELL) $(abs_builddir)/dbutil_test.sh
diff --git a/src/bin/stats/tests/Makefile.am b/src/bin/stats/tests/Makefile.am
index 01254d4..b98996a 100644
--- a/src/bin/stats/tests/Makefile.am
+++ b/src/bin/stats/tests/Makefile.am
@@ -24,6 +24,7 @@ endif
 	B10_FROM_SOURCE=$(abs_top_srcdir) \
 	BIND10_MSGQ_SOCKET_FILE=$(abs_top_builddir)/msgq_socket \
 	CONFIG_TESTDATA_PATH=$(abs_top_srcdir)/src/lib/config/tests/testdata \
+	B10_LOCKFILE_DIR_FROM_BUILD=$(abs_top_builddir) \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
 	done
 
diff --git a/src/lib/log/Makefile.am b/src/lib/log/Makefile.am
index b82eb1b..fb3aed7 100644
--- a/src/lib/log/Makefile.am
+++ b/src/lib/log/Makefile.am
@@ -2,6 +2,7 @@ SUBDIRS = . compiler tests
 
 AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CPPFLAGS += -DTOP_BUILDDIR=\"${abs_top_builddir}\"
 
 CLEANFILES = *.gcno *.gcda
 
diff --git a/src/lib/log/logger.cc b/src/lib/log/logger.cc
index d10e979..fef5627 100644
--- a/src/lib/log/logger.cc
+++ b/src/lib/log/logger.cc
@@ -179,6 +179,13 @@ Logger::fatal(const isc::log::MessageID& ident) {
     }
 }
 
+// Replace the interprocess synchronization object
+
+void
+Logger::setInterprocessSync(isc::util::InterprocessSync* sync) {
+    getLoggerPtr()->setInterprocessSync(sync);
+}
+
 // Comparison (testing only)
 
 bool
diff --git a/src/lib/log/logger.h b/src/lib/log/logger.h
index 5715bc4..6405488 100644
--- a/src/lib/log/logger.h
+++ b/src/lib/log/logger.h
@@ -25,6 +25,7 @@
 #include <log/message_types.h>
 #include <log/log_formatter.h>
 
+#include <util/interprocess_sync.h>
 
 namespace isc {
 namespace log {
@@ -98,6 +99,17 @@ public:
     {}
 };
 
+/// \brief Bad Interprocess Sync
+///
+/// Exception thrown if a bad InterprocessSync object (such as NULL) is
+/// used.
+class BadInterprocessSync : public isc::Exception {
+public:
+    BadInterprocessSync(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what)
+    {}
+};
+
 /// \brief Logger Class
 ///
 /// This class is the main class used for logging.  Use comprises:
@@ -237,6 +249,17 @@ public:
     /// \param ident Message identification.
     Formatter fatal(const MessageID& ident);
 
+    /// \brief Replace the interprocess synchronization object
+    ///
+    /// If this method is called with NULL as the argument, it throws a
+    /// BadInterprocessSync exception.
+    ///
+    /// \param sync The logger uses this synchronization object for
+    /// synchronizing output of log messages. It should be deletable and
+    /// the ownership is transferred to the logger. If NULL is passed,
+    /// a BadInterprocessSync exception is thrown.
+    void setInterprocessSync(isc::util::InterprocessSync* sync);
+
     /// \brief Equality
     ///
     /// Check if two instances of this logger refer to the same stream.
diff --git a/src/lib/log/logger_impl.cc b/src/lib/log/logger_impl.cc
index 046da13..2d6c0f4 100644
--- a/src/lib/log/logger_impl.cc
+++ b/src/lib/log/logger_impl.cc
@@ -32,12 +32,14 @@
 #include <log/message_types.h>
 
 #include <util/strutil.h>
+#include <util/interprocess_sync_file.h>
 
 // Note: as log4cplus and the BIND 10 logger have many concepts in common, and
 // thus many similar names, to disambiguate types we don't "use" the log4cplus
 // namespace: instead, all log4cplus types are explicitly qualified.
 
 using namespace std;
+using namespace isc::util;
 
 namespace isc {
 namespace log {
@@ -47,14 +49,17 @@ namespace log {
 // one compiler requires that all member variables be constructed before the
 // constructor is run, but log4cplus::Logger (the type of logger_) has no
 // default constructor.
-LoggerImpl::LoggerImpl(const string& name) : name_(expandLoggerName(name)),
-    logger_(log4cplus::Logger::getInstance(name_))
+LoggerImpl::LoggerImpl(const string& name) :
+    name_(expandLoggerName(name)),
+    logger_(log4cplus::Logger::getInstance(name_)),
+    sync_(new InterprocessSyncFile("logger"))
 {
 }
 
 // Destructor. (Here because of virtual declaration.)
 
 LoggerImpl::~LoggerImpl() {
+    delete sync_;
 }
 
 // Set the severity for logging.
@@ -102,8 +107,30 @@ LoggerImpl::lookupMessage(const MessageID& ident) {
                        MessageDictionary::globalDictionary().getText(ident)));
 }
 
+// Replace the interprocess synchronization object
+
+void
+LoggerImpl::setInterprocessSync(isc::util::InterprocessSync* sync) {
+    if (sync == NULL) {
+        isc_throw(BadInterprocessSync,
+                  "NULL was passed to setInterprocessSync()");
+    }
+
+    delete sync_;
+    sync_ = sync;
+}
+
 void
 LoggerImpl::outputRaw(const Severity& severity, const string& message) {
+    // Use an interprocess sync locker for mutual exclusion from other
+    // processes to avoid log messages getting interspersed.
+
+    InterprocessSyncLocker locker(*sync_);
+
+    if (!locker.lock()) {
+        LOG4CPLUS_ERROR(logger_, "Unable to lock logger lockfile");
+    }
+
     switch (severity) {
         case DEBUG:
             LOG4CPLUS_DEBUG(logger_, message);
@@ -124,6 +151,10 @@ LoggerImpl::outputRaw(const Severity& severity, const string& message) {
         case FATAL:
             LOG4CPLUS_FATAL(logger_, message);
     }
+
+    if (!locker.unlock()) {
+        LOG4CPLUS_ERROR(logger_, "Unable to unlock logger lockfile");
+    }
 }
 
 } // namespace log
diff --git a/src/lib/log/logger_impl.h b/src/lib/log/logger_impl.h
index 90bd41a..10d3db4 100644
--- a/src/lib/log/logger_impl.h
+++ b/src/lib/log/logger_impl.h
@@ -32,6 +32,8 @@
 #include <log/logger_level_impl.h>
 #include <log/message_types.h>
 
+#include <util/interprocess_sync.h>
+
 namespace isc {
 namespace log {
 
@@ -167,6 +169,17 @@ public:
     /// This gets you the unformatted text of message for given ID.
     std::string* lookupMessage(const MessageID& id);
 
+    /// \brief Replace the interprocess synchronization object
+    ///
+    /// If this method is called with NULL as the argument, it throws a
+    /// BadInterprocessSync exception.
+    ///
+    /// \param sync The logger uses this synchronization object for
+    /// synchronizing output of log messages. It should be deletable and
+    /// the ownership is transferred to the logger implementation.
+    /// If NULL is passed, a BadInterprocessSync exception is thrown.
+    void setInterprocessSync(isc::util::InterprocessSync* sync);
+
     /// \brief Equality
     ///
     /// Check if two instances of this logger refer to the same stream.
@@ -178,8 +191,9 @@ public:
     }
 
 private:
-    std::string         name_;              ///< Full name of this logger
-    log4cplus::Logger   logger_;            ///< Underlying log4cplus logger
+    std::string                  name_;   ///< Full name of this logger
+    log4cplus::Logger            logger_; ///< Underlying log4cplus logger
+    isc::util::InterprocessSync* sync_;
 };
 
 } // namespace log
diff --git a/src/lib/log/logger_manager.cc b/src/lib/log/logger_manager.cc
index 8a8a36b..8431c2e 100644
--- a/src/lib/log/logger_manager.cc
+++ b/src/lib/log/logger_manager.cc
@@ -28,6 +28,7 @@
 #include <log/message_initializer.h>
 #include <log/message_reader.h>
 #include <log/message_types.h>
+#include "util/interprocess_sync_null.h"
 
 using namespace std;
 
@@ -148,6 +149,13 @@ LoggerManager::readLocalMessageFile(const char* file) {
 
     MessageDictionary& dictionary = MessageDictionary::globalDictionary();
     MessageReader reader(&dictionary);
+
+    // Turn off use of any lock files. This is because this logger can
+    // be used by standalone programs which may not have write access to
+    // the local state directory (to create lock files). So we switch to
+    // using a null interprocess sync object here.
+    logger.setInterprocessSync(new isc::util::InterprocessSyncNull("logger"));
+
     try {
 
         logger.info(LOG_READING_LOCAL_FILE).arg(file);
diff --git a/src/lib/log/logger_unittest_support.cc b/src/lib/log/logger_unittest_support.cc
index a0969be..4f02b07 100644
--- a/src/lib/log/logger_unittest_support.cc
+++ b/src/lib/log/logger_unittest_support.cc
@@ -160,6 +160,9 @@ void initLogger(isc::log::Severity severity, int dbglevel) {
     // Set the local message file
     const char* localfile = getenv("B10_LOGGER_LOCALMSG");
 
+    // Set a directory for creating lockfiles when running tests
+    setenv("B10_LOCKFILE_DIR_FROM_BUILD", TOP_BUILDDIR, 1);
+
     // Initialize logging
     initLogger(root, isc::log::DEBUG, isc::log::MAX_DEBUG_LEVEL, localfile);
 
diff --git a/src/lib/log/tests/.gitignore b/src/lib/log/tests/.gitignore
index 41b863b..b0e45b9 100644
--- a/src/lib/log/tests/.gitignore
+++ b/src/lib/log/tests/.gitignore
@@ -6,6 +6,10 @@
 /initializer_unittests_2
 /local_file_test.sh
 /logger_example
+/logger_lock_test
+/logger_lock_test.sh
+/log_test_messages.cc
+/log_test_messages.h
 /run_unittests
 /severity_test.sh
 /tempdir.h
diff --git a/src/lib/log/tests/Makefile.am b/src/lib/log/tests/Makefile.am
index 6f3d768..db7dbf4 100644
--- a/src/lib/log/tests/Makefile.am
+++ b/src/lib/log/tests/Makefile.am
@@ -12,6 +12,11 @@ endif
 
 CLEANFILES = *.gcno *.gcda
 
+EXTRA_DIST = log_test_messages.mes
+BUILT_SOURCES = log_test_messages.h log_test_messages.cc
+log_test_messages.h log_test_messages.cc: log_test_messages.mes
+	$(AM_V_GEN) $(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/lib/log/tests/log_test_messages.mes
+
 noinst_PROGRAMS = logger_example
 logger_example_SOURCES = logger_example.cc
 logger_example_CPPFLAGS = $(AM_CPPFLAGS)
@@ -30,6 +35,16 @@ init_logger_test_LDADD += $(top_builddir)/src/lib/util/libutil.la
 init_logger_test_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 init_logger_test_LDADD += $(AM_LDADD) $(LOG4CPLUS_LIBS)
 
+noinst_PROGRAMS += logger_lock_test
+logger_lock_test_SOURCES = logger_lock_test.cc
+logger_lock_test_SOURCES += log_test_messages.cc log_test_messages.h
+logger_lock_test_CPPFLAGS = $(AM_CPPFLAGS)
+logger_lock_test_LDFLAGS = $(AM_LDFLAGS)
+logger_lock_test_LDADD  = $(top_builddir)/src/lib/log/liblog.la
+logger_lock_test_LDADD += $(top_builddir)/src/lib/util/libutil.la
+logger_lock_test_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+logger_lock_test_LDADD += $(AM_LDADD) $(LOG4CPLUS_LIBS)
+
 if HAVE_GTEST
 TESTS =
 
@@ -58,6 +73,7 @@ run_unittests_SOURCES += logger_manager_unittest.cc
 run_unittests_SOURCES += logger_name_unittest.cc
 run_unittests_SOURCES += logger_support_unittest.cc
 run_unittests_SOURCES += logger_unittest.cc
+run_unittests_SOURCES += log_test_messages.cc log_test_messages.h
 run_unittests_SOURCES += logger_specification_unittest.cc
 run_unittests_SOURCES += message_dictionary_unittest.cc
 run_unittests_SOURCES += message_reader_unittest.cc
@@ -104,4 +120,5 @@ check-local:
 	$(SHELL) $(abs_builddir)/destination_test.sh
 	$(SHELL) $(abs_builddir)/init_logger_test.sh
 	$(SHELL) $(abs_builddir)/local_file_test.sh
+	$(SHELL) $(abs_builddir)/logger_lock_test.sh
 	$(SHELL) $(abs_builddir)/severity_test.sh
diff --git a/src/lib/log/tests/log_test_messages.mes b/src/lib/log/tests/log_test_messages.mes
new file mode 100644
index 0000000..ed4940c
--- /dev/null
+++ b/src/lib/log/tests/log_test_messages.mes
@@ -0,0 +1,26 @@
+# Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# \brief Message Utility Message File
+#
+# This is the source of the set of messages generated by the message and
+# logging components.  The associated .h and .cc files are created by hand from
+# this file though and are not built during the build process; this is to avoid
+# the chicken-and-egg situation where we need the files to build the message
+# compiler, yet we need the compiler to build the files.
+
+$NAMESPACE isc::log
+
+% LOG_LOCK_TEST_MESSAGE this is a test message.
+This is a log message used in testing.
diff --git a/src/lib/log/tests/logger_example.cc b/src/lib/log/tests/logger_example.cc
index d3f08f3..853d48a 100644
--- a/src/lib/log/tests/logger_example.cc
+++ b/src/lib/log/tests/logger_example.cc
@@ -41,6 +41,7 @@
 
 // Include a set of message definitions.
 #include <log/log_messages.h>
+#include "util/interprocess_sync_null.h"
 
 using namespace isc::log;
 using namespace std;
@@ -280,10 +281,17 @@ int main(int argc, char** argv) {
         LoggerManager::readLocalMessageFile(argv[optind]);
     }
 
-    // Log a few messages to different loggers.
+    // Log a few messages to different loggers. Here, we switch to using
+    // null interprocess sync objects for the loggers below as the
+    // logger example can be used as a standalone program (which may not
+    // have write access to a local state directory to create
+    // lockfiles).
     isc::log::Logger logger_ex(ROOT_NAME);
+    logger_ex.setInterprocessSync(new isc::util::InterprocessSyncNull("logger"));
     isc::log::Logger logger_alpha("alpha");
+    logger_alpha.setInterprocessSync(new isc::util::InterprocessSyncNull("logger"));
     isc::log::Logger logger_beta("beta");
+    logger_beta.setInterprocessSync(new isc::util::InterprocessSyncNull("logger"));
 
     LOG_FATAL(logger_ex, LOG_WRITE_ERROR).arg("test1").arg("42");
     LOG_ERROR(logger_ex, LOG_READING_LOCAL_FILE).arg("dummy/file");
diff --git a/src/lib/log/tests/logger_lock_test.cc b/src/lib/log/tests/logger_lock_test.cc
new file mode 100644
index 0000000..d63989c
--- /dev/null
+++ b/src/lib/log/tests/logger_lock_test.cc
@@ -0,0 +1,64 @@
+// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <log/macros.h>
+#include <log/logger_support.h>
+#include <log/log_messages.h>
+#include "util/interprocess_sync.h"
+#include "log_test_messages.h"
+#include <iostream>
+
+using namespace std;
+using namespace isc::log;
+
+class MockLoggingSync : public isc::util::InterprocessSync {
+public:
+    /// \brief Constructor
+    MockLoggingSync(const std::string& component_name) :
+        InterprocessSync(component_name)
+    {}
+
+protected:
+    virtual bool lock() {
+        cout << "FIELD1 FIELD2 LOGGER_LOCK_TEST: LOCK\n";
+        return (true);
+    }
+
+    virtual bool tryLock() {
+        cout << "FIELD1 FIELD2 LOGGER_LOCK_TEST: TRYLOCK\n";
+        return (true);
+    }
+
+    virtual bool unlock() {
+        cout << "FIELD1 FIELD2 LOGGER_LOCK_TEST: UNLOCK\n";
+        return (true);
+    }
+};
+
+/// \brief Test logger lock sequence
+///
+/// A program used in testing the logger. It verifies that (1) an
+/// interprocess sync lock is first acquired by the logger, (2) the
+/// message is logged by the logger, and (3) the lock is released in
+/// that sequence.
+int
+main(int, char**) {
+    initLogger();
+    Logger logger("log");
+    logger.setInterprocessSync(new MockLoggingSync("log"));
+
+    LOG_INFO(logger, LOG_LOCK_TEST_MESSAGE);
+
+    return (0);
+}
diff --git a/src/lib/log/tests/logger_lock_test.sh.in b/src/lib/log/tests/logger_lock_test.sh.in
new file mode 100755
index 0000000..0324499
--- /dev/null
+++ b/src/lib/log/tests/logger_lock_test.sh.in
@@ -0,0 +1,46 @@
+#!/bin/sh
+# Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# Checks that the locker interprocess sync locks are acquired and
+# released correctly.
+
+failcount=0
+tempfile=@abs_builddir@/logger_lock_test_tempfile_$$
+destfile=@abs_builddir@/logger_lock_test_destfile_$$
+
+passfail() {
+    if [ $1 -eq 0 ]; then
+        echo " pass"
+    else
+        echo " FAIL"
+        failcount=`expr $failcount + $1`
+    fi
+}
+
+echo -n  "Testing that logger acquires and releases locks correctly:"
+cat > $tempfile << .
+LOGGER_LOCK_TEST: LOCK
+INFO  [bind10.log] LOG_LOCK_TEST_MESSAGE this is a test message.
+LOGGER_LOCK_TEST: UNLOCK
+.
+rm -f $destfile
+B10_LOGGER_SEVERITY=INFO B10_LOGGER_DESTINATION=stdout ./logger_lock_test > $destfile
+cut -d' ' -f3- $destfile | diff $tempfile -
+passfail $?
+
+# Tidy up.
+rm -f $tempfile $destfile
+
+exit $failcount
diff --git a/src/lib/log/tests/logger_unittest.cc b/src/lib/log/tests/logger_unittest.cc
index 069205e..a9330a9 100644
--- a/src/lib/log/tests/logger_unittest.cc
+++ b/src/lib/log/tests/logger_unittest.cc
@@ -23,6 +23,9 @@
 #include <log/logger_manager.h>
 #include <log/logger_name.h>
 #include <log/log_messages.h>
+#include "log/tests/log_test_messages.h"
+
+#include <util/interprocess_sync_file.h>
 
 using namespace isc;
 using namespace isc::log;
@@ -379,3 +382,66 @@ TEST_F(LoggerTest, LoggerNameLength) {
     }, ".*");
 #endif
 }
+
+TEST_F(LoggerTest, setInterprocessSync) {
+    // Create a logger
+    Logger logger("alpha");
+
+    EXPECT_THROW(logger.setInterprocessSync(NULL), BadInterprocessSync);
+}
+
+class MockSync : public isc::util::InterprocessSync {
+public:
+    /// \brief Constructor
+    MockSync(const std::string& component_name) :
+        InterprocessSync(component_name), was_locked_(false),
+        was_unlocked_(false)
+    {}
+
+    bool wasLocked() const {
+        return (was_locked_);
+    }
+
+    bool wasUnlocked() const {
+        return (was_unlocked_);
+    }
+
+protected:
+    bool lock() {
+        was_locked_ = true;
+        return (true);
+    }
+
+    bool tryLock() {
+        return (true);
+    }
+
+    bool unlock() {
+        was_unlocked_ = true;
+        return (true);
+    }
+
+private:
+    bool was_locked_;
+    bool was_unlocked_;
+};
+
+// Checks that the logger logs exclusively and other BIND 10 components
+// are locked out.
+
+TEST_F(LoggerTest, Lock) {
+    // Create a logger
+    Logger logger("alpha");
+
+    // Setup our own mock sync object so that we can intercept the lock
+    // call and check if a lock has been taken.
+    MockSync* sync = new MockSync("logger");
+    logger.setInterprocessSync(sync);
+
+    // Log a message and put things into play.
+    logger.setSeverity(isc::log::INFO, 100);
+    logger.info(LOG_LOCK_TEST_MESSAGE);
+
+    EXPECT_TRUE(sync->wasLocked());
+    EXPECT_TRUE(sync->wasUnlocked());
+}
diff --git a/src/lib/log/tests/run_initializer_unittests.cc b/src/lib/log/tests/run_initializer_unittests.cc
index 54ee120..6660215 100644
--- a/src/lib/log/tests/run_initializer_unittests.cc
+++ b/src/lib/log/tests/run_initializer_unittests.cc
@@ -12,6 +12,7 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include <stdlib.h>
 #include <gtest/gtest.h>
 #include <util/unittests/run_all.h>
 
diff --git a/src/lib/log/tests/run_unittests.cc b/src/lib/log/tests/run_unittests.cc
index 8a9d1e5..019a548 100644
--- a/src/lib/log/tests/run_unittests.cc
+++ b/src/lib/log/tests/run_unittests.cc
@@ -12,6 +12,7 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include <stdlib.h>
 #include <gtest/gtest.h>
 #include <util/unittests/run_all.h>
 
diff --git a/src/lib/python/isc/bind10/tests/Makefile.am b/src/lib/python/isc/bind10/tests/Makefile.am
index 658db1e..196a8b9 100644
--- a/src/lib/python/isc/bind10/tests/Makefile.am
+++ b/src/lib/python/isc/bind10/tests/Makefile.am
@@ -23,6 +23,7 @@ endif
 	echo Running test: $$pytest ; \
 	$(LIBRARY_PATH_PLACEHOLDER) \
 	PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_srcdir)/src/bin:$(abs_top_builddir)/src/bin/bind10:$(abs_top_builddir)/src/lib/util/io/.libs \
+	B10_LOCKFILE_DIR_FROM_BUILD=$(abs_top_builddir) \
 	BIND10_MSGQ_SOCKET_FILE=$(abs_top_builddir)/msgq_socket \
 		$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
 	done
diff --git a/src/lib/python/isc/config/tests/Makefile.am b/src/lib/python/isc/config/tests/Makefile.am
index 6670ee7..cb59e6f 100644
--- a/src/lib/python/isc/config/tests/Makefile.am
+++ b/src/lib/python/isc/config/tests/Makefile.am
@@ -22,6 +22,7 @@ endif
 	echo Running test: $$pytest ; \
 	$(LIBRARY_PATH_PLACEHOLDER) \
 	PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_builddir)/src/lib/python/isc/config \
+	B10_LOCKFILE_DIR_FROM_BUILD=$(abs_top_builddir) \
 	B10_TEST_PLUGIN_DIR=$(abs_top_srcdir)/src/bin/cfgmgr/plugins \
 	CONFIG_TESTDATA_PATH=$(abs_top_srcdir)/src/lib/config/tests/testdata \
 	CONFIG_WR_TESTDATA_PATH=$(abs_top_builddir)/src/lib/config/tests/testdata \
diff --git a/src/lib/python/isc/log/tests/Makefile.am b/src/lib/python/isc/log/tests/Makefile.am
index 170eee6..ec29b7a 100644
--- a/src/lib/python/isc/log/tests/Makefile.am
+++ b/src/lib/python/isc/log/tests/Makefile.am
@@ -17,6 +17,7 @@ check-local:
 	chmod +x $(abs_builddir)/log_console.py
 	$(LIBRARY_PATH_PLACEHOLDER) \
 	PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_builddir)/src/lib/python/isc/log \
+	B10_LOCKFILE_DIR_FROM_BUILD=$(abs_top_builddir) \
 	$(abs_srcdir)/check_output.sh $(abs_builddir)/log_console.py $(abs_srcdir)/console.out
 if ENABLE_PYTHON_COVERAGE
 	touch $(abs_top_srcdir)/.coverage
@@ -28,6 +29,7 @@ endif
 	$(LIBRARY_PATH_PLACEHOLDER) \
 	PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_builddir)/src/lib/python/isc/log:$(abs_top_builddir)/src/lib/log/python/.libs \
 	B10_TEST_PLUGIN_DIR=$(abs_top_srcdir)/src/bin/cfgmgr/plugins \
+	B10_LOCKFILE_DIR_FROM_BUILD=$(abs_top_builddir) \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
 	done ; \
 	for pytest in $(PYTESTS_GEN) ; do \
@@ -36,5 +38,6 @@ endif
 	$(LIBRARY_PATH_PLACEHOLDER) \
 	PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_builddir)/src/lib/python/isc/log:$(abs_top_builddir)/src/lib/log/python/.libs \
 	B10_TEST_PLUGIN_DIR=$(abs_top_srcdir)/src/bin/cfgmgr/plugins \
+	B10_LOCKFILE_DIR_FROM_BUILD=$(abs_top_builddir) \
 	$(PYCOVERAGE_RUN) $(abs_builddir)/$$pytest || exit ; \
 	done
diff --git a/src/lib/python/isc/server_common/tests/Makefile.am b/src/lib/python/isc/server_common/tests/Makefile.am
index 4829edc..3ea96da 100644
--- a/src/lib/python/isc/server_common/tests/Makefile.am
+++ b/src/lib/python/isc/server_common/tests/Makefile.am
@@ -20,5 +20,6 @@ endif
 	echo Running test: $$pytest ; \
 	$(LIBRARY_PATH_PLACEHOLDER) \
 	PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_builddir)/src/lib/dns/python/.libs \
+	B10_LOCKFILE_DIR_FROM_BUILD=$(abs_top_builddir) \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
 	done
diff --git a/src/lib/python/isc/xfrin/tests/Makefile.am b/src/lib/python/isc/xfrin/tests/Makefile.am
index 416d62b..459efc3 100644
--- a/src/lib/python/isc/xfrin/tests/Makefile.am
+++ b/src/lib/python/isc/xfrin/tests/Makefile.am
@@ -20,5 +20,6 @@ endif
 	echo Running test: $$pytest ; \
 	$(LIBRARY_PATH_PLACEHOLDER) \
 	PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_builddir)/src/lib/dns/python/.libs \
+	B10_LOCKFILE_DIR_FROM_BUILD=$(abs_top_builddir) \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
 	done
diff --git a/src/lib/util/Makefile.am b/src/lib/util/Makefile.am
index c2b3020..fad2465 100644
--- a/src/lib/util/Makefile.am
+++ b/src/lib/util/Makefile.am
@@ -4,6 +4,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/util -I$(top_builddir)/src/lib/util
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/exceptions -I$(top_builddir)/src/lib/exceptions
 AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CPPFLAGS += -DLOCKFILE_DIR=\"${localstatedir}/${PACKAGE_NAME}\"
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
 lib_LTLIBRARIES = libutil.la
@@ -12,6 +13,9 @@ libutil_la_SOURCES += locks.h lru_list.h
 libutil_la_SOURCES += strutil.h strutil.cc
 libutil_la_SOURCES += buffer.h io_utilities.h
 libutil_la_SOURCES += time_utilities.h time_utilities.cc
+libutil_la_SOURCES += interprocess_sync.h
+libutil_la_SOURCES += interprocess_sync_file.h interprocess_sync_file.cc
+libutil_la_SOURCES += interprocess_sync_null.h interprocess_sync_null.cc
 libutil_la_SOURCES += range_utilities.h
 libutil_la_SOURCES += hash/sha1.h hash/sha1.cc
 libutil_la_SOURCES += encode/base16_from_binary.h
diff --git a/src/lib/util/interprocess_sync.h b/src/lib/util/interprocess_sync.h
new file mode 100644
index 0000000..e4fa7af
--- /dev/null
+++ b/src/lib/util/interprocess_sync.h
@@ -0,0 +1,149 @@
+// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __INTERPROCESS_SYNC_H__
+#define __INTERPROCESS_SYNC_H__
+
+#include <string>
+
+namespace isc {
+namespace util {
+
+class InterprocessSyncLocker; // forward declaration
+
+/// \brief Interprocess Sync Class
+///
+/// This class specifies an interface for mutual exclusion among
+/// co-operating processes. This is an abstract class and a real
+/// implementation such as InterprocessSyncFile should be used
+/// in code. Usage is as follows:
+///
+/// 1. Client instantiates a sync object of an implementation (such as
+/// InterprocessSyncFile).
+/// 2. Client then creates an automatic (stack) object of
+/// InterprocessSyncLocker around the sync object. Such an object
+/// destroys itself and releases any acquired lock when it goes out of extent.
+/// 3. Client calls lock() method on the InterprocessSyncLocker.
+/// 4. Client performs task that needs mutual exclusion.
+/// 5. Client frees lock with unlock(), or simply returns from the basic
+/// block which forms the scope for the InterprocessSyncLocker.
+///
+/// NOTE: All implementations of InterprocessSync should keep the
+/// is_locked_ member variable updated whenever their
+/// lock()/tryLock()/unlock() implementations are called.
+class InterprocessSync {
+  // InterprocessSyncLocker is the only code outside this class that
+  // should be allowed to call the lock(), tryLock() and unlock()
+  // methods.
+  friend class InterprocessSyncLocker;
+
+public:
+    /// \brief Constructor
+    ///
+    /// Creates an interprocess synchronization object
+    ///
+    /// \param task_name Name of the synchronization task. This has to be
+    /// identical among the various processes that need to be
+    /// synchronized for the same task.
+    InterprocessSync(const std::string& task_name) :
+        task_name_(task_name), is_locked_(false)
+    {}
+
+    /// \brief Destructor
+    virtual ~InterprocessSync() {}
+
+protected:
+    /// \brief Acquire the lock (blocks if something else has acquired a
+    /// lock on the same task name)
+    ///
+    /// \return Returns true if the lock was acquired, false otherwise.
+    virtual bool lock() = 0;
+
+    /// \brief Try to acquire a lock (doesn't block)
+    ///
+    /// \return Returns true if the lock was acquired, false otherwise.
+    virtual bool tryLock() = 0;
+
+    /// \brief Release the lock
+    ///
+    /// \return Returns true if the lock was released, false otherwise.
+    virtual bool unlock() = 0;
+
+    const std::string task_name_; ///< The task name
+    bool is_locked_;              ///< Is the lock taken?
+};
+
+/// \brief Interprocess Sync Locker Class
+///
+/// This class is used for making automatic stack objects to manage
+/// locks that are released automatically when the block is exited
+/// (RAII). It is meant to be used along with InterprocessSync objects. See
+/// the description of InterprocessSync.
+class InterprocessSyncLocker {
+public:
+    /// \brief Constructor
+    ///
+    /// Creates a lock manager around a interprocess synchronization object
+    ///
+    /// \param sync The sync object which has to be locked/unlocked by
+    /// this locker object.
+    InterprocessSyncLocker(InterprocessSync& sync) :
+        sync_(sync)
+    {}
+
+    /// \brief Destructor
+    ~InterprocessSyncLocker() {
+        if (isLocked())
+            unlock();
+    }
+
+    /// \brief Acquire the lock (blocks if something else has acquired a
+    /// lock on the same task name)
+    ///
+    /// \return Returns true if the lock was acquired, false otherwise.
+    bool lock() {
+        return (sync_.lock());
+    }
+
+    /// \brief Try to acquire a lock (doesn't block)
+    ///
+    /// \return Returns true if a new lock could be acquired, false
+    ///         otherwise.
+    bool tryLock() {
+        return (sync_.tryLock());
+    }
+
+    /// \brief Check if the lock is taken
+    ///
+    /// \return Returns true if a lock is currently acquired, false
+    ///         otherwise.
+    bool isLocked() const {
+        return (sync_.is_locked_);
+    }
+
+    /// \brief Release the lock
+    ///
+    /// \return Returns true if the lock was released, false otherwise.
+    bool unlock() {
+        return (sync_.unlock());
+    }
+
+protected:
+    InterprocessSync& sync_; ///< Ref to underlying sync object
+};
+
+} // namespace util
+} // namespace isc
+
+#endif // __INTERPROCESS_SYNC_H__
diff --git a/src/lib/util/interprocess_sync_file.cc b/src/lib/util/interprocess_sync_file.cc
new file mode 100644
index 0000000..d045449
--- /dev/null
+++ b/src/lib/util/interprocess_sync_file.cc
@@ -0,0 +1,130 @@
+// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include "interprocess_sync_file.h"
+
+#include <string>
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+namespace isc {
+namespace util {
+
+InterprocessSyncFile::~InterprocessSyncFile() {
+    if (fd_ != -1) {
+        // This will also release any applied locks.
+        close(fd_);
+        // The lockfile will continue to exist, and we must not delete
+        // it.
+    }
+}
+
+bool
+InterprocessSyncFile::do_lock(int cmd, short l_type) {
+    // Open lock file only when necessary (i.e., here). This is so that
+    // if a default InterprocessSync object is replaced with another
+    // implementation, it doesn't attempt any opens.
+    if (fd_ == -1) {
+        std::string lockfile_path = LOCKFILE_DIR;
+
+        const char* const env = getenv("B10_FROM_BUILD");
+        if (env != NULL) {
+            lockfile_path = env;
+        }
+
+        const char* const env2 = getenv("B10_FROM_BUILD_LOCALSTATEDIR");
+        if (env2 != NULL) {
+            lockfile_path = env2;
+        }
+
+        const char* const env3 = getenv("B10_LOCKFILE_DIR_FROM_BUILD");
+        if (env3 != NULL) {
+            lockfile_path = env3;
+        }
+
+        lockfile_path += "/" + task_name_ + "_lockfile";
+
+        // Open the lockfile in the constructor so it doesn't do the access
+        // checks every time a message is logged.
+        const mode_t mode = umask(0111);
+        fd_ = open(lockfile_path.c_str(), O_CREAT | O_RDWR, 0660);
+        umask(mode);
+
+        if (fd_ == -1) {
+            isc_throw(InterprocessSyncFileError,
+                      "Unable to use interprocess sync lockfile: " +
+                      lockfile_path);
+        }
+    }
+
+    struct flock lock;
+
+    memset(&lock, 0, sizeof (lock));
+    lock.l_type = l_type;
+    lock.l_whence = SEEK_SET;
+    lock.l_start = 0;
+    lock.l_len = 1;
+
+    return (fcntl(fd_, cmd, &lock) == 0);
+}
+
+bool
+InterprocessSyncFile::lock() {
+    if (is_locked_) {
+        return (true);
+    }
+
+    if (do_lock(F_SETLKW, F_WRLCK)) {
+        is_locked_ = true;
+        return (true);
+    }
+
+    return (false);
+}
+
+bool
+InterprocessSyncFile::tryLock() {
+    if (is_locked_) {
+        return (true);
+    }
+
+    if (do_lock(F_SETLK, F_WRLCK)) {
+        is_locked_ = true;
+        return (true);
+    }
+
+    return (false);
+}
+
+bool
+InterprocessSyncFile::unlock() {
+    if (!is_locked_) {
+        return (true);
+    }
+
+    if (do_lock(F_SETLKW, F_UNLCK)) {
+        is_locked_ = false;
+        return (true);
+    }
+
+    return (false);
+}
+
+} // namespace util
+} // namespace isc
diff --git a/src/lib/util/interprocess_sync_file.h b/src/lib/util/interprocess_sync_file.h
new file mode 100644
index 0000000..fd8da1b
--- /dev/null
+++ b/src/lib/util/interprocess_sync_file.h
@@ -0,0 +1,91 @@
+// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __INTERPROCESS_SYNC_FILE_H__
+#define __INTERPROCESS_SYNC_FILE_H__
+
+#include <util/interprocess_sync.h>
+#include <exceptions/exceptions.h>
+
+namespace isc {
+namespace util {
+
+/// \brief InterprocessSyncFileError
+///
+/// Exception that is thrown if it's not possible to open the
+/// lock file.
+class InterprocessSyncFileError : public Exception {
+public:
+    InterprocessSyncFileError(const char* file, size_t line,
+                              const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// \brief File-based Interprocess Sync Class
+///
+/// This class specifies a concrete implementation for a file-based
+/// interprocess synchronization mechanism. Please see the
+/// InterprocessSync class documentation for usage.
+///
+/// An InterprocessSyncFileError exception may be thrown if there is an
+/// issue opening the lock file.
+///
+/// Lock files are created typically in the local state directory
+/// (var). They are typically named like "<task_name>_lockfile".
+/// This implementation opens lock files lazily (only when
+/// necessary). It also leaves the lock files lying around as multiple
+/// processes may have locks on them.
+class InterprocessSyncFile : public InterprocessSync {
+public:
+    /// \brief Constructor
+    ///
+    /// Creates a file-based interprocess synchronization object
+    ///
+    /// \param name Name of the synchronization task. This has to be
+    /// identical among the various processes that need to be
+    /// synchronized for the same task.
+    InterprocessSyncFile(const std::string& task_name) :
+        InterprocessSync(task_name), fd_(-1)
+    {}
+
+    /// \brief Destructor
+    virtual ~InterprocessSyncFile();
+
+protected:
+    /// \brief Acquire the lock (blocks if something else has acquired a
+    /// lock on the same task name)
+    ///
+    /// \return Returns true if the lock was acquired, false otherwise.
+    bool lock();
+
+    /// \brief Try to acquire a lock (doesn't block)
+    ///
+    /// \return Returns true if the lock was acquired, false otherwise.
+    bool tryLock();
+
+    /// \brief Release the lock
+    ///
+    /// \return Returns true if the lock was released, false otherwise.
+    bool unlock();
+
+private:
+    bool do_lock(int cmd, short l_type);
+
+    int fd_; ///< The descriptor for the open file
+};
+
+} // namespace util
+} // namespace isc
+
+#endif // __INTERPROCESS_SYNC_FILE_H__
diff --git a/src/lib/util/interprocess_sync_null.cc b/src/lib/util/interprocess_sync_null.cc
new file mode 100644
index 0000000..5355d57
--- /dev/null
+++ b/src/lib/util/interprocess_sync_null.cc
@@ -0,0 +1,42 @@
+// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include "interprocess_sync_null.h"
+
+namespace isc {
+namespace util {
+
+InterprocessSyncNull::~InterprocessSyncNull() {
+}
+
+bool
+InterprocessSyncNull::lock() {
+    is_locked_ = true;
+    return (true);
+}
+
+bool
+InterprocessSyncNull::tryLock() {
+    is_locked_ = true;
+    return (true);
+}
+
+bool
+InterprocessSyncNull::unlock() {
+    is_locked_ = false;
+    return (true);
+}
+
+} // namespace util
+} // namespace isc
diff --git a/src/lib/util/interprocess_sync_null.h b/src/lib/util/interprocess_sync_null.h
new file mode 100644
index 0000000..6ac0322
--- /dev/null
+++ b/src/lib/util/interprocess_sync_null.h
@@ -0,0 +1,64 @@
+// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __INTERPROCESS_SYNC_NULL_H__
+#define __INTERPROCESS_SYNC_NULL_H__
+
+#include <util/interprocess_sync.h>
+
+namespace isc {
+namespace util {
+
+/// \brief Null Interprocess Sync Class
+///
+/// This class specifies a concrete implementation for a null (no effect)
+/// interprocess synchronization mechanism. Please see the
+/// InterprocessSync class documentation for usage.
+class InterprocessSyncNull : public InterprocessSync {
+public:
+    /// \brief Constructor
+    ///
+    /// Creates a null interprocess synchronization object
+    ///
+    /// \param name Name of the synchronization task. This has to be
+    /// identical among the various processes that need to be
+    /// synchronized for the same task.
+    InterprocessSyncNull(const std::string& task_name) :
+        InterprocessSync(task_name)
+    {}
+
+    /// \brief Destructor
+    virtual ~InterprocessSyncNull();
+
+protected:
+    /// \brief Acquire the lock (never blocks)
+    ///
+    /// \return Always returns true
+    bool lock();
+
+    /// \brief Try to acquire a lock (doesn't block)
+    ///
+    /// \return Always returns true
+    bool tryLock();
+
+    /// \brief Release the lock
+    ///
+    /// \return Always returns true
+    bool unlock();
+};
+
+} // namespace util
+} // namespace isc
+
+#endif // __INTERPROCESS_SYNC_NULL_H__
diff --git a/src/lib/util/tests/Makefile.am b/src/lib/util/tests/Makefile.am
index 37dfc5e..cf1e5a5 100644
--- a/src/lib/util/tests/Makefile.am
+++ b/src/lib/util/tests/Makefile.am
@@ -28,6 +28,8 @@ run_unittests_SOURCES += filename_unittest.cc
 run_unittests_SOURCES += hex_unittest.cc
 run_unittests_SOURCES += io_utilities_unittest.cc
 run_unittests_SOURCES += lru_list_unittest.cc
+run_unittests_SOURCES += interprocess_sync_file_unittest.cc
+run_unittests_SOURCES += interprocess_sync_null_unittest.cc
 run_unittests_SOURCES += qid_gen_unittest.cc
 run_unittests_SOURCES += random_number_generator_unittest.cc
 run_unittests_SOURCES += sha1_unittest.cc
diff --git a/src/lib/util/tests/interprocess_sync_file_unittest.cc b/src/lib/util/tests/interprocess_sync_file_unittest.cc
new file mode 100644
index 0000000..a0b4109
--- /dev/null
+++ b/src/lib/util/tests/interprocess_sync_file_unittest.cc
@@ -0,0 +1,169 @@
+// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include "util/interprocess_sync_file.h"
+#include <gtest/gtest.h>
+#include <unistd.h>
+
+using namespace std;
+
+namespace isc {
+namespace util {
+
+namespace {
+unsigned char
+parentReadLockedState (int fd) {
+  unsigned char locked = 0xff;
+
+  fd_set rfds;
+  FD_ZERO(&rfds);
+  FD_SET(fd, &rfds);
+
+  // We use select() here to wait for new data on the input end of
+  // the pipe. We wait for 5 seconds (an arbitrary value) for input
+  // data, and continue if no data is available. This is done so
+  // that read() is not blocked due to some issue in the child
+  // process (and the tests continue running).
+
+  struct timeval tv;
+  tv.tv_sec = 5;
+  tv.tv_usec = 0;
+
+  const int nfds = select(fd + 1, &rfds, NULL, NULL, &tv);
+  EXPECT_EQ(1, nfds);
+
+  if (nfds == 1) {
+      // Read status
+      read(fd, &locked, sizeof(locked));
+  }
+
+  return (locked);
+}
+
+TEST(InterprocessSyncFileTest, TestLock) {
+  InterprocessSyncFile sync("test");
+  InterprocessSyncLocker locker(sync);
+
+  EXPECT_FALSE(locker.isLocked());
+  EXPECT_TRUE(locker.lock());
+  EXPECT_TRUE(locker.isLocked());
+
+  int fds[2];
+
+  // Here, we check that a lock has been taken by forking and
+  // checking from the child that a lock exists. This has to be
+  // done from a separate process as we test by trying to lock the
+  // range again on the lock file. The lock attempt would pass if
+  // done from the same process for the granted range. The lock
+  // attempt must fail to pass our check.
+
+  pipe(fds);
+
+  if (fork() == 0) {
+      unsigned char locked = 0;
+      // Child writes to pipe
+      close(fds[0]);
+
+      InterprocessSyncFile sync2("test");
+      InterprocessSyncLocker locker2(sync2);
+
+      if (!locker2.tryLock()) {
+          EXPECT_FALSE(locker2.isLocked());
+          locked = 1;
+      } else {
+          EXPECT_TRUE(locker2.isLocked());
+      }
+
+      write(fds[1], &locked, sizeof(locked));
+      close(fds[1]);
+      exit(0);
+  } else {
+      // Parent reads from pipe
+      close(fds[1]);
+
+      const unsigned char locked = parentReadLockedState(fds[0]);
+
+      close(fds[0]);
+
+      EXPECT_EQ(1, locked);
+  }
+
+  EXPECT_TRUE(locker.unlock());
+  EXPECT_FALSE(locker.isLocked());
+
+  EXPECT_EQ (0, unlink(TEST_DATA_TOPBUILDDIR "/test_lockfile"));
+}
+
+TEST(InterprocessSyncFileTest, TestMultipleFilesDirect) {
+  InterprocessSyncFile sync("test1");
+  InterprocessSyncLocker locker(sync);
+
+  EXPECT_TRUE(locker.lock());
+
+  InterprocessSyncFile sync2("test2");
+  InterprocessSyncLocker locker2(sync2);
+  EXPECT_TRUE(locker2.lock());
+  EXPECT_TRUE(locker2.unlock());
+
+  EXPECT_TRUE(locker.unlock());
+
+  EXPECT_EQ (0, unlink(TEST_DATA_TOPBUILDDIR "/test1_lockfile"));
+  EXPECT_EQ (0, unlink(TEST_DATA_TOPBUILDDIR "/test2_lockfile"));
+}
+
+TEST(InterprocessSyncFileTest, TestMultipleFilesForked) {
+  InterprocessSyncFile sync("test1");
+  InterprocessSyncLocker locker(sync);
+
+  EXPECT_TRUE(locker.lock());
+
+  int fds[2];
+
+  pipe(fds);
+
+  if (fork() == 0) {
+      unsigned char locked = 0xff;
+      // Child writes to pipe
+      close(fds[0]);
+
+      InterprocessSyncFile sync2("test2");
+      InterprocessSyncLocker locker2(sync2);
+
+      if (locker2.tryLock()) {
+          locked = 0;
+      }
+
+      write(fds[1], &locked, sizeof(locked));
+      close(fds[1]);
+      exit(0);
+  } else {
+      // Parent reads from pipe
+      close(fds[1]);
+
+      const unsigned char locked = parentReadLockedState(fds[0]);
+
+      close(fds[0]);
+
+      EXPECT_EQ(0, locked);
+  }
+
+  EXPECT_TRUE(locker.unlock());
+
+  EXPECT_EQ (0, unlink(TEST_DATA_TOPBUILDDIR "/test1_lockfile"));
+  EXPECT_EQ (0, unlink(TEST_DATA_TOPBUILDDIR "/test2_lockfile"));
+}
+}
+
+} // namespace util
+} // namespace isc
diff --git a/src/lib/util/tests/interprocess_sync_null_unittest.cc b/src/lib/util/tests/interprocess_sync_null_unittest.cc
new file mode 100644
index 0000000..70e2b07
--- /dev/null
+++ b/src/lib/util/tests/interprocess_sync_null_unittest.cc
@@ -0,0 +1,76 @@
+// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include "util/interprocess_sync_null.h"
+#include <gtest/gtest.h>
+
+using namespace std;
+
+namespace isc {
+namespace util {
+
+TEST(InterprocessSyncNullTest, TestNull) {
+  InterprocessSyncNull sync("test1");
+  InterprocessSyncLocker locker(sync);
+
+  // Check if the is_locked_ flag is set correctly during lock().
+  EXPECT_FALSE(locker.isLocked());
+  EXPECT_TRUE(locker.lock());
+  EXPECT_TRUE(locker.isLocked());
+
+  // lock() must always return true (this is called 4 times, just an
+  // arbitrary number)
+  EXPECT_TRUE(locker.lock());
+  EXPECT_TRUE(locker.lock());
+  EXPECT_TRUE(locker.lock());
+  EXPECT_TRUE(locker.lock());
+
+  // Check if the is_locked_ flag is set correctly during unlock().
+  EXPECT_TRUE(locker.isLocked());
+  EXPECT_TRUE(locker.unlock());
+  EXPECT_FALSE(locker.isLocked());
+
+  // unlock() must always return true (this is called 4 times, just an
+  // arbitrary number)
+  EXPECT_TRUE(locker.unlock());
+  EXPECT_TRUE(locker.unlock());
+  EXPECT_TRUE(locker.unlock());
+  EXPECT_TRUE(locker.unlock());
+
+  // Check if the is_locked_ flag is set correctly during tryLock().
+  EXPECT_FALSE(locker.isLocked());
+  EXPECT_TRUE(locker.tryLock());
+  EXPECT_TRUE(locker.isLocked());
+
+  // tryLock() must always return true (this is called 4 times, just an
+  // arbitrary number)
+  EXPECT_TRUE(locker.tryLock());
+  EXPECT_TRUE(locker.tryLock());
+  EXPECT_TRUE(locker.tryLock());
+  EXPECT_TRUE(locker.tryLock());
+
+  // Random order (should all return true)
+  EXPECT_TRUE(locker.unlock());
+  EXPECT_TRUE(locker.lock());
+  EXPECT_TRUE(locker.tryLock());
+  EXPECT_TRUE(locker.lock());
+  EXPECT_TRUE(locker.unlock());
+  EXPECT_TRUE(locker.lock());
+  EXPECT_TRUE(locker.tryLock());
+  EXPECT_TRUE(locker.unlock());
+  EXPECT_TRUE(locker.unlock());
+}
+
+} // namespace util
+} // namespace isc
diff --git a/src/lib/util/tests/run_unittests.cc b/src/lib/util/tests/run_unittests.cc
index a2181cf..8789a9c 100644
--- a/src/lib/util/tests/run_unittests.cc
+++ b/src/lib/util/tests/run_unittests.cc
@@ -14,10 +14,12 @@
 
 #include <gtest/gtest.h>
 #include <util/unittests/run_all.h>
+#include <stdlib.h>
 
 int
 main(int argc, char* argv[]) {
     ::testing::InitGoogleTest(&argc, argv);
 
+    setenv("B10_LOCKFILE_DIR_FROM_BUILD", TEST_DATA_TOPBUILDDIR, 1);
     return (isc::util::unittests::run_all());
 }



More information about the bind10-changes mailing list