=== modified file 'debian/changelog'
--- debian/changelog	2015-02-09 21:27:35 +0000
+++ debian/changelog	2015-02-23 20:59:44 +0000
@@ -1,7 +1,30 @@
+mir (0.11.1) UNRELEASED; urgency=medium
+
+  * New upstream release 0.11.1 (https://launchpad.net/mir/+milestone/0.11.1)
+    - Packaging changes:
+      . Client platform packages now include the Mir client platform ABI 
+        number. Thusly, mir-client-platform-(mesa|android) is replaced by 
+        mir-client-platform-(mesa|android)2
+      . Server graphics platform packages now include the Mir graphics
+        platform ABI number. Thusly, mir-platform-graphics-(mesa|android)
+        is replaced by mir-platform-graphics-(mesa|android)1
+    - Bug fixes:
+      . [regression] Platform libraries and packages are not versioned thus
+        are not installable in parallel (LP: #1423591)
+      . [regression] Deadlock in TimeoutFrameDroppingPolicy logic (LP: #1421255)
+ 
+ -- Alberto Aguirre <alberto.aguirre@canonical.com>  Mon, 23 Feb 2015 14:22:40 -0600
+
 mir (0.11.0+15.04.20150209.1-0ubuntu1) vivid; urgency=medium
 
   [ Daniel van Vugt ]
   * New upstream release 0.11.0 (https://launchpad.net/mir/+milestone/0.11.0)
+    - Packaging changes:
+      . Due to changes in the Mir driver model the client platforms are no
+        longer versioned by soname. Thusly libmirplatform5driver-(mesa|android) is
+        replaced by mir-client-platform-(mesa-android). A new package
+        mir-client-platform-mesa-dev is introduced containing headers
+        previously in mirplatform-dev.
     - Enhancements:
       . Lots more major plumbing in the Android code, on the path to
         supporting external displays.

=== modified file 'debian/control'
--- debian/control	2015-01-27 03:02:22 +0000
+++ debian/control	2015-02-23 20:59:44 +0000
@@ -61,7 +61,7 @@
 
 #TODO: Packaging infrastructure for better dependency generation,
 #      ala pkg-xorg's xviddriver:Provides and ABI detection.
-Package: libmirserver29
+Package: libmirserver30
 Section: libs
 Architecture: i386 amd64 armhf arm64
 Multi-Arch: same
@@ -128,7 +128,7 @@
 Architecture: i386 amd64 armhf arm64
 Multi-Arch: same
 Pre-Depends: ${misc:Pre-Depends}
-Depends: libmirserver29 (= ${binary:Version}),
+Depends: libmirserver30 (= ${binary:Version}),
          libmirplatform-dev (= ${binary:Version}),
          libmircommon-dev (= ${binary:Version}),
          libglm-dev,
@@ -268,7 +268,7 @@
  Contains the shared libraries required for the Mir server and client.
 
 # Longer-term these drivers should move out-of-tree
-Package: mir-platform-graphics-mesa
+Package: mir-platform-graphics-mesa1
 Section: libs
 Architecture: i386 amd64 armhf arm64
 Multi-Arch: same
@@ -282,7 +282,7 @@
  Contains the shared libraries required for the Mir server to interact with
  the hardware platform using the Mesa drivers.
 
-Package: mir-platform-graphics-android
+Package: mir-platform-graphics-android1
 Section: libs
 Architecture: i386 amd64 armhf
 Multi-Arch: same
@@ -296,7 +296,7 @@
  Contains the shared libraries required for the Mir server to interact with
  the hardware platform using the Android drivers.
 
-Package: mir-client-platform-mesa
+Package: mir-client-platform-mesa2
 Section: libs
 Architecture: i386 amd64 armhf arm64
 Multi-Arch: same
@@ -325,7 +325,7 @@
  Contains header files required to use the platform specific capabilities of
  the Mir Mesa backend.
 
-Package: mir-client-platform-android
+Package: mir-client-platform-android2
 Section: libs
 Architecture: i386 amd64 armhf
 Multi-Arch: same
@@ -345,8 +345,8 @@
 Multi-Arch: same
 Pre-Depends: ${misc:Pre-Depends}
 Depends: ${misc:Depends},
-         mir-platform-graphics-mesa,
-         mir-client-platform-mesa,
+         mir-platform-graphics-mesa1,
+         mir-client-platform-mesa2,
 Description: Display server for Ubuntu - desktop driver metapackage
  Mir is a display server running on linux systems, with a focus on efficiency,
  robust operation and a well-defined driver model.
@@ -360,8 +360,8 @@
 Multi-Arch: same
 Pre-Depends: ${misc:Pre-Depends}
 Depends: ${misc:Depends},
-         mir-platform-graphics-android,
-         mir-client-platform-android,
+         mir-platform-graphics-android1,
+         mir-client-platform-android2,
 Description: Display server for Ubuntu - android driver metapackage
  Mir is a display server running on linux systems, with a focus on efficiency,
  robust operation and a well-defined driver model.

=== renamed file 'debian/libmirserver29.install' => 'debian/libmirserver30.install'
--- debian/libmirserver29.install	2015-01-21 09:03:53 +0000
+++ debian/libmirserver30.install	2015-02-23 20:59:44 +0000
@@ -1,1 +1,1 @@
-usr/lib/*/libmirserver.so.29
+usr/lib/*/libmirserver.so.30

=== renamed file 'debian/mir-client-platform-android.install' => 'debian/mir-client-platform-android2.install'
--- debian/mir-client-platform-android.install	2015-01-21 07:34:50 +0000
+++ debian/mir-client-platform-android2.install	2015-02-23 20:59:44 +0000
@@ -1,1 +1,1 @@
-usr/lib/*/mir/client-platform/android.so
+usr/lib/*/mir/client-platform/android.so.2

=== renamed file 'debian/mir-client-platform-mesa.install' => 'debian/mir-client-platform-mesa2.install'
--- debian/mir-client-platform-mesa.install	2015-01-21 07:34:50 +0000
+++ debian/mir-client-platform-mesa2.install	2015-02-23 20:59:44 +0000
@@ -1,1 +1,1 @@
-usr/lib/*/mir/client-platform/mesa.so
+usr/lib/*/mir/client-platform/mesa.so.2

=== renamed file 'debian/mir-platform-graphics-android.install' => 'debian/mir-platform-graphics-android1.install'
--- debian/mir-platform-graphics-android.install	2015-01-14 13:09:48 +0000
+++ debian/mir-platform-graphics-android1.install	2015-02-23 20:59:44 +0000
@@ -1,1 +1,1 @@
-usr/lib/*/mir/server-platform/graphics-android.so
+usr/lib/*/mir/server-platform/graphics-android.so.1

=== renamed file 'debian/mir-platform-graphics-mesa.install' => 'debian/mir-platform-graphics-mesa1.install'
--- debian/mir-platform-graphics-mesa.install	2015-01-14 13:09:48 +0000
+++ debian/mir-platform-graphics-mesa1.install	2015-02-23 20:59:44 +0000
@@ -1,1 +1,1 @@
-usr/lib/*/mir/server-platform/graphics-mesa.so
+usr/lib/*/mir/server-platform/graphics-mesa.so.1

=== modified file 'include/server/mir/time/timer.h'
--- include/server/mir/time/timer.h	2015-01-21 07:34:50 +0000
+++ include/server/mir/time/timer.h	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -14,6 +14,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
+ *              Alberto Aguirre <alberto.aguirre@canonical.com>
  */
 
 
@@ -47,7 +48,7 @@
      * \return A handle to an Alarm that will fire after delay ms.
      */
     virtual std::unique_ptr<Alarm> notify_in(std::chrono::milliseconds delay,
-                                             std::function<void()> callback) = 0;
+                                             std::function<void()> const& callback) = 0;
     /**
      * \brief Create an Alarm that calls the callback at the specified time
      *
@@ -57,7 +58,7 @@
      * \return A handle to an Alarm that will fire after delay ms.
      */
     virtual std::unique_ptr<Alarm> notify_at(Timestamp time_point,
-                                             std::function<void()> callback) = 0;
+                                             std::function<void()> const& callback) = 0;
     /**
      * \brief Create an Alarm that will not fire until scheduled
      *
@@ -65,7 +66,30 @@
      *
      * \return A handle to an Alarm that can later be scheduled
      */
-    virtual std::unique_ptr<Alarm> create_alarm(std::function<void()> callback) = 0;
+    virtual std::unique_ptr<Alarm> create_alarm(std::function<void()> const& callback) = 0;
+
+    /**
+     * \brief Create an Alarm that will not fire until scheduled
+     *
+     * The lock/unlock functions allow the user to preserve lock ordering
+     * in situations where Alarm methods need to be called under external lock
+     * and the callback implementation needs to run code protected by the same
+     * lock. An alarm implementation may have internal locks of its own, which
+     * maybe acquired during callback dispatching; to preserve lock ordering
+     * the given lock function will be invoked during callback dispatch before
+     * any internal locks are acquired.
+     *
+     * \param callback Function to call when the Alarm signals
+     * \param lock     Function called within callback dispatching context
+     *                 before the alarm implementation acquires any internal
+     *                 lock
+     * \param unlock   Function called within callback dispatching context after
+     *                 the alarm implementation releases any internal lock
+     *
+     * \return A handle to an Alarm that can later be scheduled
+     */
+    virtual std::unique_ptr<Alarm> create_alarm(std::function<void()> const& callback,
+        std::function<void()> const& lock, std::function<void()> const& unlock) = 0;
 
     Timer(Timer const&) = delete;
     Timer& operator=(Timer const&) = delete;

=== modified file 'server-ABI-sha1sums'
--- server-ABI-sha1sums	2015-02-03 15:07:44 +0000
+++ server-ABI-sha1sums	2015-02-23 20:59:44 +0000
@@ -114,4 +114,4 @@
 e4786cdcd111bd6270db25d40129c4e415cb4347  include/server/mir/shell/shell_wrapper.h
 114cc8c0b12ee4fd78d86c8f3309546e4dc68c9f  include/server/mir/terminate_with_current_exception.h
 1b8c2a763c8f5f00b737c3a187db2304676f8076  include/server/mir/time/alarm.h
-a134c7b86e9c3b191f1004abe7bbdceed8ac42ee  include/server/mir/time/timer.h
+1a42680df4952714537e4e7c6bb5a03bc7fa3f38  include/server/mir/time/timer.h

=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt	2015-01-27 03:02:22 +0000
+++ src/CMakeLists.txt	2015-02-23 20:59:44 +0000
@@ -1,5 +1,4 @@
-# We need MIRPLATFORM_ABI and MIR_PLATFORM_DRIVER_BINARY in both libmirplatform 
-# and the platform implementations.
+# We need MIRPLATFORM_ABI in both libmirplatform and the platform implementations.
 set(MIRPLATFORM_ABI 6)
 
 # We need MIR_CLIENT_PLATFORM_PATH in both libmirclient and the platform
@@ -42,3 +41,7 @@
 set(MIR_COMMON_REFERENCES ${MIR_COMMON_REFERENCES} PARENT_SCOPE)
 set(MIR_CLIENT_PLATFORM_PATH ${MIR_CLIENT_PLATFORM_PATH} PARENT_SCOPE)
 set(MIR_SERVER_PLATFORM_PATH ${MIR_SERVER_PLATFORM_PATH} PARENT_SCOPE)
+
+# We need the ABI versions in the tests
+set(MIR_SERVER_GRAPHICS_PLATFORM_ABI ${MIR_SERVER_GRAPHICS_PLATFORM_ABI} PARENT_SCOPE)
+set(MIR_CLIENT_PLATFORM_ABI ${MIR_CLIENT_PLATFORM_ABI} PARENT_SCOPE)

=== modified file 'src/client/CMakeLists.txt'
--- src/client/CMakeLists.txt	2015-01-27 03:02:22 +0000
+++ src/client/CMakeLists.txt	2015-02-23 20:59:44 +0000
@@ -24,11 +24,10 @@
 )
 
 set(MIRCLIENT_ABI 8)
-set(CLIENT_PLATFORM_VERSION "MIR_CLIENT_PLATFORM_2")
 set(symbol_map ${CMAKE_SOURCE_DIR}/src/client/symbols.map)
 
 add_definitions(-DMIR_CLIENT_PLATFORM_PATH="${MIR_CLIENT_PLATFORM_PATH}/")
-add_definitions(-DCLIENT_PLATFORM_VERSION="${CLIENT_PLATFORM_VERSION}")
+add_definitions(-DCLIENT_PLATFORM_VERSION="${MIR_CLIENT_PLATFORM_VERSION}")
 add_definitions(-DMIR_LOGGING_COMPONENT_FALLBACK="mirclient")
 
 add_subdirectory(rpc/)

=== modified file 'src/common/sharedlibrary/shared_library_prober.cpp'
--- src/common/sharedlibrary/shared_library_prober.cpp	2014-09-02 00:28:47 +0000
+++ src/common/sharedlibrary/shared_library_prober.cpp	2015-02-23 20:59:44 +0000
@@ -37,6 +37,14 @@
     }
     return std::error_code{};
 }
+
+// Libraries can be of the form libname.so(.X.Y)
+bool path_has_library_extension(boost::filesystem::path const& path)
+{
+    return path.extension().string() == ".so" ||
+           path.string().find(".so.") != std::string::npos;
+}
+
 }
 
 std::vector<std::shared_ptr<mir::SharedLibrary>>
@@ -57,7 +65,7 @@
     std::vector<std::shared_ptr<mir::SharedLibrary>> libraries;
     for (; iterator != boost::filesystem::directory_iterator() ; ++iterator)
     {
-        if (iterator->path().extension().string() == ".so")
+        if (path_has_library_extension(iterator->path()))
         {
             try
             {

=== modified file 'src/include/server/mir/compositor/frame_dropping_policy_factory.h'
--- src/include/server/mir/compositor/frame_dropping_policy_factory.h	2015-01-21 07:34:50 +0000
+++ src/include/server/mir/compositor/frame_dropping_policy_factory.h	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -14,6 +14,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
+ *              Alberto Aguirre <alberto.aguirre@canonical.com>
  */
 
 #ifndef MIR_COMPOSITOR_FRAME_DROPPING_POLICY_FACTORY_H_
@@ -44,11 +45,27 @@
     FrameDroppingPolicyFactory& operator=(FrameDroppingPolicyFactory const&) = delete;
 
     /**
-     * \brief Create a FrameDroppingPolicy that will call \a drop_frame when it decides to drop a frame
-     * \param drop_frame    Function to call when a frame needs to be dropped
-     * \return              The policy object.
+     * \brief Create a FrameDroppingPolicy that will call \a drop_frame when it
+     *       decides to drop a frame
+     *
+     * The lock/unlock functions allow the user to preserve lock ordering
+     * in situations where FrameDroppingPolicy methods need to be called under
+     * external lock and the callback implementation needs to run code protected
+     * by the same lock. A FrameDroppingPolicy implementation may have internal
+     * locks of its own, which maybe acquired during callback dispatching;
+     * to preserve lock ordering the given lock function will be invoked during
+     * callback dispatch before any internal locks are acquired.
+     *
+     * \param drop_frame Function to call when a frame needs to be dropped
+     * \param lock       Function called within the callback dispatcher context
+     *                   before any internal locks are acquired.
+     * \param unlock     Function called within the callback dispatcher context
+     *                   after any internal locks are released.
      */
-    virtual std::unique_ptr<FrameDroppingPolicy> create_policy(std::function<void(void)> drop_frame) const = 0;
+    virtual std::unique_ptr<FrameDroppingPolicy> create_policy(
+        std::function<void()> const& drop_frame,
+        std::function<void()> const& lock,
+        std::function<void()> const& unlock) const = 0;
 };
 
 }

=== modified file 'src/include/server/mir/glib_main_loop.h'
--- src/include/server/mir/glib_main_loop.h	2015-01-21 07:34:50 +0000
+++ src/include/server/mir/glib_main_loop.h	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -72,14 +72,19 @@
 
     std::unique_ptr<mir::time::Alarm> notify_in(
         std::chrono::milliseconds delay,
-        std::function<void()> callback) override;
+        std::function<void()> const& callback) override;
 
     std::unique_ptr<mir::time::Alarm> notify_at(
         mir::time::Timestamp t,
-        std::function<void()> callback) override;
-
-    std::unique_ptr<mir::time::Alarm> create_alarm(
-        std::function<void()> callback) override;
+        std::function<void()> const& callback) override;
+
+    std::unique_ptr<mir::time::Alarm> create_alarm(
+        std::function<void()> const& callback) override;
+
+    std::unique_ptr<mir::time::Alarm> create_alarm(
+        std::function<void()> const& callback,
+        std::function<void()> const& lock,
+        std::function<void()> const& unlock) override;
 
     void reprocess_all_sources();
 

=== modified file 'src/include/server/mir/glib_main_loop_sources.h'
--- src/include/server/mir/glib_main_loop_sources.h	2015-01-21 07:34:50 +0000
+++ src/include/server/mir/glib_main_loop_sources.h	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -65,6 +65,8 @@
     GMainContext* main_context,
     std::shared_ptr<time::Clock> const& clock,
     std::function<void()> const& handler,
+    std::function<void()> const& lock,
+    std::function<void()> const& unlock,
     time::Timestamp target_time);
 
 class FdSources

=== modified file 'src/platform/graphics/platform_probe.cpp'
--- src/platform/graphics/platform_probe.cpp	2014-12-17 13:48:10 +0000
+++ src/platform/graphics/platform_probe.cpp	2015-02-23 20:59:44 +0000
@@ -47,7 +47,7 @@
         {
             // Tried to probe a SharedLibrary that isn't a platform module?
             ml::log(ml::Severity::warning,
-                    std::string{"Failed to probe module. Not a platform library? Error: "} + err.what(),
+                    std::string{"Failed to probe module. Not a platform library or incorrect ABI version? Error: "} + err.what(),
                     "Platform Probing");
         }
     }

=== modified file 'src/platforms/CMakeLists.txt'
--- src/platforms/CMakeLists.txt	2015-01-27 03:02:22 +0000
+++ src/platforms/CMakeLists.txt	2015-02-23 20:59:44 +0000
@@ -3,7 +3,9 @@
 # This ABI is much smaller than the full libmirplatform ABI.
 #
 # TODO: Add an extra driver-ABI check target.
-set(MIR_SERVER_GRAPHICS_PLATFORM_VERSION "MIR_GRAPHICS_PLATFORM_1")
+set(MIR_SERVER_GRAPHICS_PLATFORM_ABI 1)
+set(MIR_SERVER_GRAPHICS_PLATFORM_ABI ${MIR_SERVER_GRAPHICS_PLATFORM_ABI} PARENT_SCOPE)
+set(MIR_SERVER_GRAPHICS_PLATFORM_VERSION "MIR_GRAPHICS_PLATFORM_${MIR_SERVER_GRAPHICS_PLATFORM_ABI}")
 set(MIR_SERVER_GRAPHICS_PLATFORM_VERSION ${MIR_SERVER_GRAPHICS_PLATFORM_VERSION} PARENT_SCOPE)
 
 set(MIR_SERVER_PLATFORM_PATH
@@ -14,6 +16,11 @@
   PARENT_SCOPE
 )
 
+set(MIR_CLIENT_PLATFORM_ABI 2)
+set(MIR_CLIENT_PLATFORM_ABI ${MIR_CLIENT_PLATFORM_ABI} PARENT_SCOPE)
+set(MIR_CLIENT_PLATFORM_VERSION "MIR_CLIENT_PLATFORM_${MIR_CLIENT_PLATFORM_ABI}")
+set(MIR_CLIENT_PLATFORM_VERSION ${MIR_CLIENT_PLATFORM_VERSION} PARENT_SCOPE)
+
 set(server_common_include_dirs
   ${PROJECT_SOURCE_DIR}/include/platform
 )

=== modified file 'src/platforms/android/client/CMakeLists.txt'
--- src/platforms/android/client/CMakeLists.txt	2015-01-27 03:02:22 +0000
+++ src/platforms/android/client/CMakeLists.txt	2015-02-23 20:59:44 +0000
@@ -26,6 +26,7 @@
   OUTPUT_NAME android
   LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}/client-modules
   PREFIX ""
+  SUFFIX ".so.${MIR_CLIENT_PLATFORM_ABI}"
   LINK_FLAGS "-Wl,--version-script,${symbol_map}"
 )
 

=== modified file 'src/platforms/android/server/CMakeLists.txt'
--- src/platforms/android/server/CMakeLists.txt	2015-01-27 03:02:22 +0000
+++ src/platforms/android/server/CMakeLists.txt	2015-02-23 20:59:44 +0000
@@ -63,6 +63,7 @@
   OUTPUT_NAME graphics-android
   LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}/server-modules
   PREFIX ""
+  SUFFIX ".so.${MIR_SERVER_GRAPHICS_PLATFORM_ABI}"
   LINK_FLAGS "-Wl,--exclude-libs=ALL -Wl,--version-script,${symbol_map}"
 )
 

=== modified file 'src/platforms/mesa/client/CMakeLists.txt'
--- src/platforms/mesa/client/CMakeLists.txt	2015-01-22 09:00:14 +0000
+++ src/platforms/mesa/client/CMakeLists.txt	2015-02-23 20:59:44 +0000
@@ -28,6 +28,7 @@
   OUTPUT_NAME mesa
   LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}/client-modules
   PREFIX ""
+  SUFFIX ".so.${MIR_CLIENT_PLATFORM_ABI}"
   LINK_FLAGS "-Wl,--version-script,${symbol_map}"
 )
 

=== modified file 'src/platforms/mesa/server/CMakeLists.txt'
--- src/platforms/mesa/server/CMakeLists.txt	2015-01-27 03:02:22 +0000
+++ src/platforms/mesa/server/CMakeLists.txt	2015-02-23 20:59:44 +0000
@@ -64,6 +64,7 @@
   OUTPUT_NAME graphics-mesa
   LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}/server-modules
   PREFIX ""
+  SUFFIX ".so.${MIR_SERVER_GRAPHICS_PLATFORM_ABI}"
   LINK_FLAGS "-Wl,--exclude-libs=ALL -Wl,--version-script,${symbol_map}"
 )
 

=== modified file 'src/server/CMakeLists.txt'
--- src/server/CMakeLists.txt	2015-02-02 12:18:18 +0000
+++ src/server/CMakeLists.txt	2015-02-23 20:59:44 +0000
@@ -106,7 +106,7 @@
   ${CMAKE_SOURCE_DIR}/include/server/mir DESTINATION "include/mirserver"
 )
 
-set(MIRSERVER_ABI 29) # Be sure to increment MIR_VERSION_MINOR at the same time
+set(MIRSERVER_ABI 30) # Be sure to increment MIR_VERSION_MINOR at the same time
 set(symbol_map ${CMAKE_CURRENT_SOURCE_DIR}/symbols.map)
 
 set_target_properties(

=== modified file 'src/server/compositor/buffer_queue.cpp'
--- src/server/compositor/buffer_queue.cpp	2015-01-22 09:12:04 +0000
+++ src/server/compositor/buffer_queue.cpp	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -132,11 +132,18 @@
     if (nbuffers == 1)
         free_buffers.push_back(current_compositor_buffer);
 
+    // A lock_guard will be created by the policy dispatcher invoking the given "lock" lambda
+    // before it acquires any internal locks of its own.
     framedrop_policy = policy_provider.create_policy([this]
     {
-       std::unique_lock<decltype(guard)> lock{guard};
-       drop_frame(std::move(lock));
-    });
+        // We ignore any ongoing snapshotting as it could lead to deadlock.
+        // In order to wait the guard_lock needs to be released; a BufferQueue::release
+        // call can sneak in at that time from a different thread which
+        // can invoke framedrop_policy methods
+        drop_frame(guard_lock, ignore_snapshot);
+    },
+    [this] { guard_lock = std::move(std::unique_lock<decltype(guard)>{guard}); },
+    [this] { if (guard_lock.owns_lock()) guard_lock.unlock(); });
 }
 
 void mc::BufferQueue::client_acquire(mc::BufferQueue::Callback complete)
@@ -149,7 +156,7 @@
     {
         auto const buffer = free_buffers.back();
         free_buffers.pop_back();
-        give_buffer_to_client(buffer, std::move(lock));
+        give_buffer_to_client(buffer, lock);
         return;
     }
 
@@ -162,14 +169,14 @@
     {
         auto const& buffer = gralloc->alloc_buffer(the_properties);
         buffers.push_back(buffer);
-        give_buffer_to_client(buffer.get(), std::move(lock));
+        give_buffer_to_client(buffer.get(), lock);
         return;
     }
 
     /* Last resort, drop oldest buffer from the ready queue */
     if (frame_dropping_enabled)
     {
-        drop_frame(std::move(lock));
+        drop_frame(lock, wait_for_snapshot);
         return;
     }
 
@@ -342,7 +349,7 @@
         {
             free_buffers.push_back(pop(ready_to_composite_queue));
         }
-        give_buffer_to_client(buffer, std::move(lock));
+        give_buffer_to_client(buffer, lock, ignore_snapshot);
     }
 }
 
@@ -382,7 +389,15 @@
 
 void mc::BufferQueue::give_buffer_to_client(
     mg::Buffer* buffer,
-    std::unique_lock<std::mutex> lock)
+    std::unique_lock<std::mutex>& lock)
+{
+    give_buffer_to_client(buffer, lock, wait_for_snapshot);
+}
+
+void mc::BufferQueue::give_buffer_to_client(
+    mg::Buffer* buffer,
+    std::unique_lock<std::mutex>& lock,
+    SnapshotWait wait_type)
 {
     /* Clears callback */
     auto give_to_client_cb = std::move(pending_client_notifications.front());
@@ -402,7 +417,7 @@
     }
 
     /* Don't give to the client just yet if there's a pending snapshot */
-    if (!resize_buffer && contains(buffer, pending_snapshots))
+    if (wait_type == wait_for_snapshot && !resize_buffer && contains(buffer, pending_snapshots))
     {
         snapshot_released.wait(lock,
             [&]{ return !contains(buffer, pending_snapshots); });
@@ -439,7 +454,7 @@
     if (!pending_client_notifications.empty())
     {
         framedrop_policy->swap_unblocked();
-        give_buffer_to_client(buffer, std::move(lock));
+        give_buffer_to_client(buffer, lock);
     }
     else if (!frame_dropping_enabled && buffers.size() > size_t(nbuffers))
     {
@@ -465,7 +480,7 @@
         free_buffers.push_back(buffer);
 }
 
-void mc::BufferQueue::drop_frame(std::unique_lock<std::mutex> lock)
+void mc::BufferQueue::drop_frame(std::unique_lock<std::mutex>& lock, SnapshotWait wait_type)
 {
     // Make sure there is a client waiting for the frame before we drop it.
     // If not, then there's nothing to do.
@@ -517,7 +532,7 @@
         buffer_to_give = buffer.get();
     }
         
-    give_buffer_to_client(buffer_to_give, std::move(lock));
+    give_buffer_to_client(buffer_to_give, lock, wait_type);
 }
 
 void mc::BufferQueue::drop_old_buffers()

=== modified file 'src/server/compositor/buffer_queue.h'
--- src/server/compositor/buffer_queue.h	2015-01-21 08:53:28 +0000
+++ src/server/compositor/buffer_queue.h	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -66,13 +66,21 @@
     void drop_client_requests() override;
 
 private:
-    void give_buffer_to_client(graphics::Buffer* buffer,
-        std::unique_lock<std::mutex> lock);
+    enum SnapshotWait
+    {
+        wait_for_snapshot,
+        ignore_snapshot
+    };
+    void give_buffer_to_client(graphics::Buffer* buffer,
+        std::unique_lock<std::mutex>& lock);
+    void give_buffer_to_client(graphics::Buffer* buffer,
+        std::unique_lock<std::mutex>& lock, SnapshotWait wait_type);
     void release(graphics::Buffer* buffer,
         std::unique_lock<std::mutex> lock);
-    void drop_frame(std::unique_lock<std::mutex> lock);
+    void drop_frame(std::unique_lock<std::mutex>& lock, SnapshotWait wait_type);
 
     mutable std::mutex guard;
+    std::unique_lock<decltype(guard)> guard_lock;
 
     std::vector<std::shared_ptr<graphics::Buffer>> buffers;
     std::deque<graphics::Buffer*> ready_to_composite_queue;

=== modified file 'src/server/compositor/timeout_frame_dropping_policy_factory.cpp'
--- src/server/compositor/timeout_frame_dropping_policy_factory.cpp	2015-01-21 07:34:50 +0000
+++ src/server/compositor/timeout_frame_dropping_policy_factory.cpp	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -14,6 +14,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
+ *              Alberto Aguirre <alberto.aguirre@canonical.com>
  */
 
 #include "mir/compositor/frame_dropping_policy.h"
@@ -34,7 +35,9 @@
 public:
     TimeoutFrameDroppingPolicy(std::shared_ptr<mir::time::Timer> const& timer,
                                std::chrono::milliseconds timeout,
-                               std::function<void(void)> drop_frame);
+                               std::function<void()> const& drop_frame,
+                               std::function<void()> const& lock,
+                               std::function<void()> const& unlock);
 
     void swap_now_blocking() override;
     void swap_unblocked() override;
@@ -50,7 +53,9 @@
 
 TimeoutFrameDroppingPolicy::TimeoutFrameDroppingPolicy(std::shared_ptr<mir::time::Timer> const& timer,
                                                        std::chrono::milliseconds timeout,
-                                                       std::function<void(void)> drop_frame)
+                                                       std::function<void()> const& drop_frame,
+                                                       std::function<void()> const& lock,
+                                                       std::function<void()> const& unlock)
     : timeout{timeout},
       pending_swaps{0},
       alarm{timer->create_alarm([this, drop_frame]
@@ -59,7 +64,7 @@
             drop_frame();
             if (--pending_swaps > 0)
                 alarm->reschedule_in(this->timeout);
-        })}
+        }, lock, unlock)}
 {
 }
 
@@ -81,15 +86,18 @@
 }
 }
 
-mc::TimeoutFrameDroppingPolicyFactory::TimeoutFrameDroppingPolicyFactory(std::shared_ptr<mir::time::Timer> const& timer,
-                                                                         std::chrono::milliseconds timeout)
+mc::TimeoutFrameDroppingPolicyFactory::TimeoutFrameDroppingPolicyFactory(
+    std::shared_ptr<mir::time::Timer> const& timer,
+    std::chrono::milliseconds timeout)
     : timer{timer},
       timeout{timeout}
 {
 }
 
-
-std::unique_ptr<mc::FrameDroppingPolicy> mc::TimeoutFrameDroppingPolicyFactory::create_policy(std::function<void ()> drop_frame) const
+std::unique_ptr<mc::FrameDroppingPolicy>
+mc::TimeoutFrameDroppingPolicyFactory::create_policy(std::function<void()> const& drop_frame,
+    std::function<void()> const& lock,
+    std::function<void()> const& unlock) const
 {
-    return std::unique_ptr<mc::FrameDroppingPolicy>{new TimeoutFrameDroppingPolicy{timer, timeout, drop_frame}};
+    return std::unique_ptr<mc::FrameDroppingPolicy>{new TimeoutFrameDroppingPolicy{timer, timeout, drop_frame, lock, unlock}};
 }

=== modified file 'src/server/compositor/timeout_frame_dropping_policy_factory.h'
--- src/server/compositor/timeout_frame_dropping_policy_factory.h	2014-05-22 20:48:20 +0000
+++ src/server/compositor/timeout_frame_dropping_policy_factory.h	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -14,6 +14,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
+ *              Alberto Aguirre <alberto.aguirre@canonical.com>
  */
 
 
@@ -44,7 +45,10 @@
     TimeoutFrameDroppingPolicyFactory(std::shared_ptr<mir::time::Timer> const& timer,
                                       std::chrono::milliseconds timeout);
 
-    std::unique_ptr<FrameDroppingPolicy> create_policy(std::function<void(void)> drop_frame) const override;
+    std::unique_ptr<FrameDroppingPolicy> create_policy(
+        std::function<void()> const& drop_frame,
+        std::function<void()> const& lock,
+        std::function<void()> const& unlock) const override;
 private:
     std::shared_ptr<mir::time::Timer> const timer;
     std::chrono::milliseconds timeout;

=== modified file 'src/server/glib_main_loop.cpp'
--- src/server/glib_main_loop.cpp	2015-01-21 07:34:50 +0000
+++ src/server/glib_main_loop.cpp	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -14,6 +14,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
+ *              Alberto Aguirre <alberto.aguirre@canonical.com>
  */
 
 #include "mir/glib_main_loop.h"
@@ -33,10 +34,14 @@
     AlarmImpl(
         GMainContext* main_context,
         std::shared_ptr<mir::time::Clock> const& clock,
-        std::function<void()> const& callback)
+        std::function<void()> const& callback,
+        std::function<void()> const& lock,
+        std::function<void()> const& unlock)
         : main_context{main_context},
           clock{clock},
           callback{callback},
+          ext_lock{lock},
+          ext_unlock{unlock},
           state_{State::cancelled}
     {
     }
@@ -70,6 +75,8 @@
             main_context,
             clock,
             [&] { state_ = State::triggered; callback(); },
+            ext_lock,
+            ext_unlock,
             time_point);
 
         return true;
@@ -80,6 +87,8 @@
     GMainContext* main_context;
     std::shared_ptr<mir::time::Clock> const clock;
     std::function<void()> const callback;
+    std::function<void()> const ext_lock;
+    std::function<void()> const ext_unlock;
     State state_;
     mir::detail::GSourceHandle gsource;
 };
@@ -223,7 +232,7 @@
 
 std::unique_ptr<mir::time::Alarm> mir::GLibMainLoop::notify_in(
     std::chrono::milliseconds delay,
-    std::function<void()> callback)
+    std::function<void()> const& callback)
 {
     auto alarm = create_alarm(callback);
 
@@ -234,7 +243,7 @@
 
 std::unique_ptr<mir::time::Alarm> mir::GLibMainLoop::notify_at(
     mir::time::Timestamp t,
-    std::function<void()> callback)
+    std::function<void()> const& callback)
 {
     auto alarm = create_alarm(callback);
 
@@ -244,7 +253,15 @@
 }
 
 std::unique_ptr<mir::time::Alarm> mir::GLibMainLoop::create_alarm(
-    std::function<void()> callback)
+    std::function<void()> const& callback)
+{
+    return create_alarm(callback, []{}, []{});
+}
+
+std::unique_ptr<mir::time::Alarm> mir::GLibMainLoop::create_alarm(
+    std::function<void()> const& callback,
+    std::function<void()> const& lock,
+    std::function<void()> const& unlock)
 {
     auto const callback_with_exception_handling =
         [this, callback]
@@ -254,7 +271,7 @@
         };
 
     return std::unique_ptr<mir::time::Alarm>{
-        new AlarmImpl(main_context, clock, callback_with_exception_handling)};
+        new AlarmImpl(main_context, clock, callback_with_exception_handling, lock, unlock)};
 }
 
 void mir::GLibMainLoop::reprocess_all_sources()

=== modified file 'src/server/glib_main_loop_sources.cpp'
--- src/server/glib_main_loop_sources.cpp	2015-01-21 07:34:50 +0000
+++ src/server/glib_main_loop_sources.cpp	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -14,11 +14,13 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
+ *              Alberto Aguirre <alberto.aguirre@canonical.com>
  */
 
 #include "mir/glib_main_loop_sources.h"
 #include "mir/recursive_read_write_mutex.h"
 #include "mir/thread_safe_list.h"
+#include "mir/raii.h"
 
 #include <algorithm>
 #include <atomic>
@@ -233,18 +235,25 @@
     GMainContext* main_context,
     std::shared_ptr<time::Clock> const& clock,
     std::function<void()> const& handler,
+    std::function<void()> const& lock,
+    std::function<void()> const& unlock,
     time::Timestamp target_time)
 {
     struct TimerContext
     {
         TimerContext(std::shared_ptr<time::Clock> const& clock,
                      std::function<void()> const& handler,
+                     std::function<void()> const& lock,
+                     std::function<void()> const& unlock,
                      time::Timestamp target_time)
-            : clock{clock}, handler{handler}, target_time{target_time}, enabled{true}
+            : clock{clock}, handler{handler}, lock{lock}, unlock{unlock},
+              target_time{target_time}, enabled{true}
         {
         }
         std::shared_ptr<time::Clock> clock;
         std::function<void()> handler;
+        std::function<void()> lock;
+        std::function<void()> unlock;
         time::Timestamp target_time;
         bool enabled;
         mir::RecursiveReadWriteMutex mutex;
@@ -284,6 +293,9 @@
         {
             auto& ctx = reinterpret_cast<TimerGSource*>(source)->ctx;
 
+            // Caller may pass std::function objects to preserve locking
+            // order during callback dispatching, so aquire them first.
+            auto caller_lock = mir::raii::paired_calls(std::ref(ctx.lock), std::ref(ctx.unlock));
             RecursiveReadLock lock{ctx.mutex};
             if (ctx.enabled)
                 ctx.handler();
@@ -321,7 +333,7 @@
     auto const timer_gsource = reinterpret_cast<TimerGSource*>(static_cast<GSource*>(gsource));
 
     timer_gsource->ctx_constructed = false;
-    new (&timer_gsource->ctx) TimerContext{clock, handler, target_time};
+    new (&timer_gsource->ctx) TimerContext{clock, handler, lock, unlock, target_time};
     timer_gsource->ctx_constructed = true;
 
     g_source_attach(gsource, main_context);

=== modified file 'src/server/symbols.map'
--- src/server/symbols.map	2015-02-03 15:07:44 +0000
+++ src/server/symbols.map	2015-02-23 20:59:44 +0000
@@ -1,4 +1,4 @@
-MIR_SERVER_29 {
+MIR_SERVER_30 {
  global:
   extern "C++" {
 # Symbols not yet picked up by script

=== modified file 'tests/acceptance-tests/test_symbols_required_by_mesa.cpp'
--- tests/acceptance-tests/test_symbols_required_by_mesa.cpp	2015-01-27 03:02:22 +0000
+++ tests/acceptance-tests/test_symbols_required_by_mesa.cpp	2015-02-23 20:59:44 +0000
@@ -28,7 +28,7 @@
 
 TEST(SymbolsRequiredByMesa, are_exported_by_client_platform_mesa)
 {
-    auto const handle = dlopen(mtf::client_platform("mesa.so").c_str(), RTLD_LAZY);
+    auto const handle = dlopen(mtf::client_platform("mesa").c_str(), RTLD_LAZY);
     ASSERT_THAT(handle, NotNull());
 
     auto const sym = dlsym(handle, "mir_client_mesa_egl_native_display_is_valid");

=== modified file 'tests/include/mir_test_doubles/mock_frame_dropping_policy_factory.h'
--- tests/include/mir_test_doubles/mock_frame_dropping_policy_factory.h	2014-05-22 20:48:20 +0000
+++ tests/include/mir_test_doubles/mock_frame_dropping_policy_factory.h	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -14,6 +14,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
+ *              Alberto Aguirre <alberto.aguirre@canonical.com>
  */
 
 
@@ -23,6 +24,8 @@
 #include "mir/compositor/frame_dropping_policy_factory.h"
 #include "mir/compositor/frame_dropping_policy.h"
 
+#include "mir_test/gmock_fixes.h"
+
 #include <unordered_set>
 #include <functional>
 
@@ -42,7 +45,9 @@
 class MockFrameDroppingPolicy : public mc::FrameDroppingPolicy
 {
 public:
-    MockFrameDroppingPolicy(std::function<void(void)> callback,
+    MockFrameDroppingPolicy(std::function<void()> const& callback,
+                            std::function<void()> const& lock,
+                            std::function<void()> const& unlock,
                             MockFrameDroppingPolicyFactory const* parent);
     ~MockFrameDroppingPolicy();
 
@@ -55,14 +60,19 @@
     friend class MockFrameDroppingPolicyFactory;
     void parent_destroyed();
 
-    std::function<void(void)> callback;
+    std::function<void()> callback;
+    std::function<void()> lock;
+    std::function<void()> unlock;
     MockFrameDroppingPolicyFactory const* parent;
 };
 
 class MockFrameDroppingPolicyFactory : public mc::FrameDroppingPolicyFactory
 {
 public:
-    std::unique_ptr<mc::FrameDroppingPolicy> create_policy(std::function<void(void)> drop_frame) const override;
+    std::unique_ptr<mc::FrameDroppingPolicy> create_policy(
+        std::function<void()> const& drop_frame,
+        std::function<void()> const& lock,
+        std::function<void()> const& unlock) const override;
 
     ~MockFrameDroppingPolicyFactory();
 
@@ -75,6 +85,15 @@
     mutable std::unordered_set<MockFrameDroppingPolicy*> policies;
 };
 
+class FrameDroppingPolicyFactoryMock : public mc::FrameDroppingPolicyFactory
+{
+public:
+    MOCK_CONST_METHOD3(create_policy, std::unique_ptr<mc::FrameDroppingPolicy>(
+                     std::function<void()> const&,
+                     std::function<void()> const&,
+                     std::function<void()> const&));
+};
+
 }
 }
 }

=== modified file 'tests/include/mir_test_doubles/mock_main_loop.h'
--- tests/include/mir_test_doubles/mock_main_loop.h	2014-06-24 14:12:25 +0000
+++ tests/include/mir_test_doubles/mock_main_loop.h	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 3 as
@@ -52,11 +52,19 @@
     MOCK_METHOD1(pause_processing_for,void (void const*));
     MOCK_METHOD1(resume_processing_for,void (void const*));
 
-    MOCK_METHOD2(notify_in, std::unique_ptr<time::Alarm>(std::chrono::milliseconds delay,
-                                           std::function<void(void)> callback));
-    MOCK_METHOD2(notify_at, std::unique_ptr<time::Alarm>(time::Timestamp time_point,
-                                           std::function<void(void)> callback));
-    MOCK_METHOD1(create_alarm, std::unique_ptr<time::Alarm>(std::function<void ()> callback));
+    MOCK_METHOD2(notify_in,
+                 std::unique_ptr<time::Alarm>(std::chrono::milliseconds delay,
+                                              std::function<void()> const& callback));
+    MOCK_METHOD2(notify_at,
+                 std::unique_ptr<time::Alarm>(time::Timestamp time_point,
+                                              std::function<void()> const& callback));
+    MOCK_METHOD1(create_alarm, std::unique_ptr<time::Alarm>(std::function<void()> const& callback));
+    MOCK_METHOD3(create_alarm,
+                 std::unique_ptr<time::Alarm>(
+                     std::function<void()> const& callback,
+                     std::function<void()> const& lock,
+                     std::function<void()> const& unlock));
+
 };
 
 }

=== modified file 'tests/include/mir_test_doubles/mock_timer.h'
--- tests/include/mir_test_doubles/mock_timer.h	2014-05-22 20:48:20 +0000
+++ tests/include/mir_test_doubles/mock_timer.h	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -14,6 +14,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
+ *              Alberto Aguirre <alberto.aguirre@canonical.com>
  */
 
 #ifndef MIR_TEST_DOUBLES_MOCK_TIMER_H_
@@ -36,11 +37,12 @@
     FakeTimer(std::shared_ptr<FakeClock> const& clock);
 
     std::unique_ptr<time::Alarm> notify_in(std::chrono::milliseconds delay,
-                                           std::function<void(void)> callback) override;
+                                           std::function<void()> const& callback) override;
     std::unique_ptr<time::Alarm> notify_at(time::Timestamp time_point,
-                                           std::function<void(void)> callback) override;
-    std::unique_ptr<time::Alarm> create_alarm(std::function<void ()> callback) override;
-
+                                           std::function<void()> const& callback) override;
+    std::unique_ptr<time::Alarm> create_alarm(std::function<void()> const& callback) override;
+    std::unique_ptr<time::Alarm> create_alarm(std::function<void()> const& callback,
+        std::function<void()> const& lock, std::function<void()> const& unlock) override;
 private:
     std::shared_ptr<FakeClock> const clock;
 };

=== modified file 'tests/include/mir_test_doubles/stub_frame_dropping_policy_factory.h'
--- tests/include/mir_test_doubles/stub_frame_dropping_policy_factory.h	2014-05-22 20:48:20 +0000
+++ tests/include/mir_test_doubles/stub_frame_dropping_policy_factory.h	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -14,6 +14,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
+ *              Alberto Aguirre <alberto.aguirre@canonical.com>
  */
 
 
@@ -46,9 +47,12 @@
 class StubFrameDroppingPolicyFactory : public mc::FrameDroppingPolicyFactory
 {
 public:
-    std::unique_ptr<mc::FrameDroppingPolicy> create_policy(std::function<void(void)>) const override
+    std::unique_ptr<mc::FrameDroppingPolicy> create_policy(
+        std::function<void()> const&,
+        std::function<void()> const&,
+        std::function<void()> const& ) const override
     {
-        return std::unique_ptr<mc::FrameDroppingPolicy>{new StubFrameDroppingPolicy};
+       return std::unique_ptr<mc::FrameDroppingPolicy>{new StubFrameDroppingPolicy};
     }
 };
 

=== modified file 'tests/include/mir_test_doubles/stub_timer.h'
--- tests/include/mir_test_doubles/stub_timer.h	2015-01-21 07:34:50 +0000
+++ tests/include/mir_test_doubles/stub_timer.h	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -51,12 +51,12 @@
 
 class StubTimer : public mir::time::Timer
 {
-    std::unique_ptr<mir::time::Alarm> notify_in(std::chrono::milliseconds, std::function<void(void)>) override
+    std::unique_ptr<mir::time::Alarm> notify_in(std::chrono::milliseconds, std::function<void()> const&) override
     {
         return std::unique_ptr<mir::time::Alarm>{new StubAlarm};
     }
 
-    std::unique_ptr<mir::time::Alarm> notify_at(mir::time::Timestamp, std::function<void(void)>) override
+    std::unique_ptr<mir::time::Alarm> notify_at(mir::time::Timestamp, std::function<void()> const&) override
     {
         return std::unique_ptr<mir::time::Alarm>{new StubAlarm};
     }

=== modified file 'tests/include/mir_test_doubles/triggered_main_loop.h'
--- tests/include/mir_test_doubles/triggered_main_loop.h	2015-01-27 11:47:52 +0000
+++ tests/include/mir_test_doubles/triggered_main_loop.h	2015-02-23 20:59:44 +0000
@@ -39,7 +39,7 @@
 
     void register_fd_handler(std::initializer_list<int> fds, void const* owner, fd_callback const& handler) override;
     void unregister_fd_handler(void const* owner) override;
-    std::unique_ptr<mir::time::Alarm> notify_in(std::chrono::milliseconds delay, callback call) override;
+    std::unique_ptr<mir::time::Alarm> notify_in(std::chrono::milliseconds delay, callback const& call) override;
     void enqueue(void const* owner, ServerAction const& action) override;
 
     void trigger_pending_fds();

=== modified file 'tests/include/mir_test_framework/client_platform_factory.h'
--- tests/include/mir_test_framework/client_platform_factory.h	2015-02-03 15:07:44 +0000
+++ tests/include/mir_test_framework/client_platform_factory.h	2015-02-23 20:59:44 +0000
@@ -37,7 +37,7 @@
     mtd::MockClientContext ctx;
     ON_CALL(ctx, populate_server_package(_))
         .WillByDefault(Invoke([](MirPlatformPackage& package) { ::memset(&package, 0, sizeof(package)); }));
-    platform_library = std::make_shared<mir::SharedLibrary>(client_platform("android.so"));
+    platform_library = std::make_shared<mir::SharedLibrary>(client_platform("android"));
     auto platform_factory = platform_library->load_function<mir::client::CreateClientPlatform>("create_client_platform");
     return platform_factory(&ctx);
 }
@@ -46,7 +46,7 @@
     mir::client::ClientContext* client_context)
 {
     using namespace testing;
-    platform_library = std::make_shared<mir::SharedLibrary>(client_platform("mesa.so"));
+    platform_library = std::make_shared<mir::SharedLibrary>(client_platform("mesa"));
     auto platform_factory = platform_library->load_function<mir::client::CreateClientPlatform>("create_client_platform");
     return platform_factory(client_context);
 }

=== modified file 'tests/mir_test_doubles/mock_frame_dropping_policy_factory.cpp'
--- tests/mir_test_doubles/mock_frame_dropping_policy_factory.cpp	2014-05-22 20:48:20 +0000
+++ tests/mir_test_doubles/mock_frame_dropping_policy_factory.cpp	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -14,6 +14,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
+ *              Alberto Aguirre <alberto.aguirre@canonical.com>
  */
 
 #include "mir_test_doubles/mock_frame_dropping_policy_factory.h"
@@ -21,9 +22,13 @@
 namespace mc = mir::compositor;
 namespace mtd = mir::test::doubles;
 
-mtd::MockFrameDroppingPolicy::MockFrameDroppingPolicy(std::function<void(void)> callback,
+mtd::MockFrameDroppingPolicy::MockFrameDroppingPolicy(std::function<void()> const& callback,
+                                                      std::function<void()> const& lock,
+                                                      std::function<void()> const& unlock,
                                                       MockFrameDroppingPolicyFactory const* parent)
         : callback{callback},
+          lock{lock},
+          unlock{unlock},
           parent{parent}
 {
 }
@@ -36,7 +41,9 @@
 
 void mtd::MockFrameDroppingPolicy::trigger()
 {
+    lock();
     callback();
+    unlock();
 }
 
 void mtd::MockFrameDroppingPolicy::parent_destroyed()
@@ -45,9 +52,10 @@
 }
 
 std::unique_ptr<mc::FrameDroppingPolicy>
-mtd::MockFrameDroppingPolicyFactory::create_policy(std::function<void(void)> drop_frame) const
+mtd::MockFrameDroppingPolicyFactory::create_policy(std::function<void()> const& drop_frame,
+    std::function<void()> const& lock, std::function<void()> const& unlock) const
 {
-    auto policy = new ::testing::NiceMock<MockFrameDroppingPolicy>{drop_frame, this};
+    auto policy = new ::testing::NiceMock<MockFrameDroppingPolicy>{drop_frame, lock, unlock, this};
     policies.insert(policy);
     return std::unique_ptr<mc::FrameDroppingPolicy>{policy};
 }

=== modified file 'tests/mir_test_doubles/mock_timer.cpp'
--- tests/mir_test_doubles/mock_timer.cpp	2015-01-21 07:34:50 +0000
+++ tests/mir_test_doubles/mock_timer.cpp	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -14,6 +14,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
+ *              Alberto Aguirre <alberto.aguirre@canonical.com>
  */
 
 #include "mir_test_doubles/mock_timer.h"
@@ -27,7 +28,10 @@
 class FakeAlarm : public mir::time::Alarm
 {
 public:
-    FakeAlarm(std::function<void(void)> callback, std::shared_ptr<mt::FakeClock> const& clock);
+    FakeAlarm(std::function<void()> const& callback,
+              std::function<void()> const& lock,
+              std::function<void()> const& unlock,
+              std::shared_ptr<mt::FakeClock> const& clock);
     ~FakeAlarm() override;
 
 
@@ -39,9 +43,13 @@
 private:    
     struct InternalState
     {
-        explicit InternalState(std::function<void(void)> callback);
+        explicit InternalState(std::function<void()> const& callback,
+                               std::function<void()> const& lock,
+                               std::function<void()> const& unlock);
         State state;
-        std::function<void(void)> const callback;
+        std::function<void()> const callback;
+        std::function<void()> const lock;
+        std::function<void()> const unlock;
         mt::FakeClock::time_point threshold;
     };
 
@@ -51,13 +59,20 @@
     std::shared_ptr<mt::FakeClock> const clock;
 };
 
-FakeAlarm::InternalState::InternalState(std::function<void(void)> callback)
-    : state{mir::time::Alarm::pending}, callback{callback}
+FakeAlarm::InternalState::InternalState(
+    std::function<void()> const& callback,
+    std::function<void()> const& lock,
+    std::function<void()> const& unlock)
+    : state{mir::time::Alarm::pending}, callback{callback}, lock{lock}, unlock{unlock}
 {
 }
 
-FakeAlarm::FakeAlarm(std::function<void(void)> callback, std::shared_ptr<mt::FakeClock> const& clock)
-    : internal_state{std::make_shared<InternalState>(callback)}, clock{clock}
+FakeAlarm::FakeAlarm(
+    std::function<void()> const& callback,
+    std::function<void()> const& lock,
+    std::function<void()> const& unlock,
+    std::shared_ptr<mt::FakeClock> const& clock)
+    : internal_state{std::make_shared<InternalState>(callback, lock, unlock)}, clock{clock}
 {
 }
 
@@ -88,7 +103,9 @@
         if (now > state.threshold)
         {
             state.state = triggered;
+            state.lock();
             state.callback();
+            state.unlock();
             return false;
         }
         return true;
@@ -128,22 +145,28 @@
 }
 
 std::unique_ptr<mir::time::Alarm> mtd::FakeTimer::notify_in(std::chrono::milliseconds delay,
-                                                            std::function<void(void)> callback)
+                                                            std::function<void()> const& callback)
 {
-    auto alarm = std::unique_ptr<mir::time::Alarm>{new FakeAlarm{callback, clock}};
+    auto alarm = std::unique_ptr<mir::time::Alarm>{new FakeAlarm{callback, []{}, []{}, clock}};
     alarm->reschedule_in(delay);
     return std::move(alarm);
 }
 
 std::unique_ptr<mir::time::Alarm> mtd::FakeTimer::notify_at(time::Timestamp time_point,
-                                                            std::function<void(void)> callback)
+                                                            std::function<void()> const& callback)
 {
-    auto alarm = std::unique_ptr<mir::time::Alarm>{new FakeAlarm{callback, clock}};
+    auto alarm = std::unique_ptr<mir::time::Alarm>{new FakeAlarm{callback, []{}, []{}, clock}};
     alarm->reschedule_for(time_point);
     return std::move(alarm);
 }
 
-std::unique_ptr<mir::time::Alarm> mir::test::doubles::FakeTimer::create_alarm(std::function<void(void)> callback)
-{
-    return std::unique_ptr<mir::time::Alarm>{new FakeAlarm{callback, clock}};
+std::unique_ptr<mir::time::Alarm> mir::test::doubles::FakeTimer::create_alarm(std::function<void()> const& callback)
+{
+    return std::unique_ptr<mir::time::Alarm>{new FakeAlarm{callback, []{}, []{}, clock}};
+}
+
+std::unique_ptr<mir::time::Alarm> mir::test::doubles::FakeTimer::create_alarm(std::function<void()> const& callback,
+    std::function<void()> const& lock, std::function<void()> const& unlock)
+{
+    return std::unique_ptr<mir::time::Alarm>{new FakeAlarm{callback, lock, unlock, clock}};
 }

=== modified file 'tests/mir_test_doubles/triggered_main_loop.cpp'
--- tests/mir_test_doubles/triggered_main_loop.cpp	2015-01-27 11:47:52 +0000
+++ tests/mir_test_doubles/triggered_main_loop.cpp	2015-02-23 20:59:44 +0000
@@ -85,8 +85,9 @@
         action();
 }
 
-std::unique_ptr<mir::time::Alarm> mtd::TriggeredMainLoop::notify_in(std::chrono::milliseconds delay,
-                                            callback call)
+std::unique_ptr<mir::time::Alarm>
+mtd::TriggeredMainLoop::notify_in(std::chrono::milliseconds delay,
+                                  callback const& call)
 {
     base::notify_in(delay, call);
     timeout_callbacks.push_back(call);

=== modified file 'tests/mir_test_framework/CMakeLists.txt'
--- tests/mir_test_framework/CMakeLists.txt	2015-01-27 03:02:22 +0000
+++ tests/mir_test_framework/CMakeLists.txt	2015-02-23 20:59:44 +0000
@@ -14,6 +14,8 @@
 add_definitions(
     -DMIR_CLIENT_PLATFORM_PATH="${MIR_CLIENT_PLATFORM_PATH}"
     -DMIR_SERVER_PLATFORM_PATH="${MIR_SERVER_PLATFORM_PATH}"
+    -DMIR_CLIENT_PLATFORM_ABI_STRING="${MIR_CLIENT_PLATFORM_ABI}"
+    -DMIR_SERVER_GRAPHICS_PLATFORM_ABI_STRING="${MIR_SERVER_GRAPHICS_PLATFORM_ABI}"
     )
 
 set(

=== modified file 'tests/mir_test_framework/executable_path.cpp'
--- tests/mir_test_framework/executable_path.cpp	2015-01-27 03:02:22 +0000
+++ tests/mir_test_framework/executable_path.cpp	2015-02-23 20:59:44 +0000
@@ -47,10 +47,15 @@
 
 std::string mir_test_framework::server_platform(std::string const& name)
 {
+    std::string libname{name};
+
+    if (libname.find(".so") == std::string::npos)
+        libname += ".so." MIR_SERVER_GRAPHICS_PLATFORM_ABI_STRING;
+
     for (auto const& option :
          {library_path() + "/server-modules/", library_path() + "/server-platform/", std::string(MIR_SERVER_PLATFORM_PATH) + '/'})
     {
-        auto path_to_test = option + name;
+        auto path_to_test = option + libname;
         if (boost::filesystem::exists(path_to_test))
             return path_to_test;
     }
@@ -60,10 +65,15 @@
 
 std::string mir_test_framework::client_platform(std::string const& name)
 {
+    std::string libname{name};
+
+    if (libname.find(".so") == std::string::npos)
+        libname += ".so." MIR_CLIENT_PLATFORM_ABI_STRING;
+
     for (auto const& option :
          {library_path() + "/client-modules/", library_path() + "/client-platform/", std::string(MIR_CLIENT_PLATFORM_PATH) + '/'})
     {
-        auto path_to_test = option + name;
+        auto path_to_test = option + libname;
         if (boost::filesystem::exists(path_to_test))
             return path_to_test;
     }

=== modified file 'tests/unit-tests/client/test_client_platform.cpp'
--- tests/unit-tests/client/test_client_platform.cpp	2015-02-02 12:18:18 +0000
+++ tests/unit-tests/client/test_client_platform.cpp	2015-02-23 20:59:44 +0000
@@ -79,7 +79,7 @@
 };
 
 #ifdef MIR_BUILD_PLATFORM_ANDROID
-ClientPlatformTraits const android_platform{"android.so",
+ClientPlatformTraits const android_platform{"android",
                                             [](MirPlatformPackage& pkg)
                                             {
                                                 ::memset(&pkg, 0, sizeof(pkg));
@@ -94,7 +94,7 @@
 #endif
 
 #ifdef MIR_BUILD_PLATFORM_MESA
-ClientPlatformTraits const mesa_platform{"mesa.so",
+ClientPlatformTraits const mesa_platform{"mesa",
                                          [](MirPlatformPackage& pkg)
                                          {
                                              ::memset(&pkg, 0, sizeof(pkg));

=== modified file 'tests/unit-tests/client/test_probing_client_platform_factory.cpp'
--- tests/unit-tests/client/test_probing_client_platform_factory.cpp	2015-02-02 12:18:18 +0000
+++ tests/unit-tests/client/test_probing_client_platform_factory.cpp	2015-02-23 20:59:44 +0000
@@ -36,10 +36,10 @@
 {
     std::vector<std::shared_ptr<mir::SharedLibrary>> modules;
 #ifdef MIR_BUILD_PLATFORM_MESA
-    modules.push_back(std::make_shared<mir::SharedLibrary>(mtf::client_platform("mesa.so")));
+    modules.push_back(std::make_shared<mir::SharedLibrary>(mtf::client_platform("mesa")));
 #endif
 #ifdef MIR_BUILD_PLATFORM_ANDROID
-    modules.push_back(std::make_shared<mir::SharedLibrary>(mtf::client_platform("android.so")));
+    modules.push_back(std::make_shared<mir::SharedLibrary>(mtf::client_platform("android")));
 #endif
     return modules;
 }

=== modified file 'tests/unit-tests/compositor/test_buffer_queue.cpp'
--- tests/unit-tests/compositor/test_buffer_queue.cpp	2015-01-22 09:12:04 +0000
+++ tests/unit-tests/compositor/test_buffer_queue.cpp	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2013-2014 Canonical Ltd.
+ * Copyright © 2013-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 3 as
@@ -1687,3 +1687,12 @@
     auto comp2 = q.compositor_acquire(new_compositor_id);
     ASSERT_THAT(comp2->id(), Eq(handle2->id()));
 }
+
+TEST_F(BufferQueueTest, creates_policy_with_lock_unlock_functions)
+{
+    int const nbuffers = 3;
+
+    mtd::FrameDroppingPolicyFactoryMock mock_policy_factory;
+    EXPECT_CALL(mock_policy_factory, create_policy(_, _, _));
+    mc::BufferQueue q(nbuffers, allocator, basic_properties, mock_policy_factory);
+}

=== modified file 'tests/unit-tests/compositor/test_timeout_frame_dropping_policy.cpp'
--- tests/unit-tests/compositor/test_timeout_frame_dropping_policy.cpp	2014-05-22 20:48:20 +0000
+++ tests/unit-tests/compositor/test_timeout_frame_dropping_policy.cpp	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3,
@@ -14,16 +14,18 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
+ *              Alberto Aguirre <alberto.aguirre@canonical.com>
  */
 
 #include "src/server/compositor/timeout_frame_dropping_policy_factory.h"
 #include "mir/compositor/frame_dropping_policy.h"
 
 #include "mir_test_doubles/mock_timer.h"
-
+#include "mir_test/auto_unblock_thread.h"
 #include "mir_test/gmock_fixes.h"
 
 #include <stdexcept>
+#include <mutex>
 
 #include <gtest/gtest.h>
 #include <gmock/gmock.h>
@@ -40,7 +42,7 @@
     bool frame_dropped{false};
 
     mc::TimeoutFrameDroppingPolicyFactory factory{timer, timeout};
-    auto policy = factory.create_policy([&frame_dropped]{ frame_dropped = true; });
+    auto policy = factory.create_policy([&frame_dropped]{ frame_dropped = true; }, []{}, []{});
 
     clock->advance_time(timeout + std::chrono::milliseconds{1});
     EXPECT_FALSE(frame_dropped);
@@ -54,7 +56,7 @@
     bool frame_dropped{false};
 
     mc::TimeoutFrameDroppingPolicyFactory factory{timer, timeout};
-    auto policy = factory.create_policy([&frame_dropped]{ frame_dropped = true; });
+    auto policy = factory.create_policy([&frame_dropped]{ frame_dropped = true; }, []{}, []{});
     policy->swap_now_blocking();
 
     clock->advance_time(timeout - std::chrono::milliseconds{1});
@@ -71,7 +73,7 @@
 
     bool frame_dropped{false};
     mc::TimeoutFrameDroppingPolicyFactory factory{timer, timeout};
-    auto policy = factory.create_policy([&frame_dropped]{ frame_dropped = true; });
+    auto policy = factory.create_policy([&frame_dropped]{ frame_dropped = true; }, []{}, []{});
 
     policy->swap_now_blocking();
     policy->swap_unblocked();
@@ -89,7 +91,7 @@
 
     bool frame_dropped{false};
     mc::TimeoutFrameDroppingPolicyFactory factory{timer, timeout};
-    auto policy = factory.create_policy([&frame_dropped]{ frame_dropped = true; });
+    auto policy = factory.create_policy([&frame_dropped]{ frame_dropped = true; }, []{}, []{});
 
     policy->swap_now_blocking();
     policy->swap_now_blocking();
@@ -119,7 +121,7 @@
 
     bool frame_dropped{false};
     mc::TimeoutFrameDroppingPolicyFactory factory{timer, timeout};
-    auto policy = factory.create_policy([&frame_dropped]{ frame_dropped = true; });
+    auto policy = factory.create_policy([&frame_dropped]{ frame_dropped = true; }, []{}, []{});
 
     policy->swap_now_blocking();
     policy->swap_now_blocking();
@@ -142,7 +144,7 @@
 
     bool frame_dropped{false};
     mc::TimeoutFrameDroppingPolicyFactory factory{timer, timeout};
-    auto policy = factory.create_policy([&frame_dropped]{ frame_dropped = true; });
+    auto policy = factory.create_policy([&frame_dropped]{ frame_dropped = true; }, []{}, []{});
 
     policy->swap_now_blocking();
     clock->advance_time(timeout - std::chrono::milliseconds{1});
@@ -160,7 +162,7 @@
 
     bool frame_dropped{false};
     mc::TimeoutFrameDroppingPolicyFactory factory{timer, timeout};
-    auto policy = factory.create_policy([&frame_dropped]{ frame_dropped = true; });
+    auto policy = factory.create_policy([&frame_dropped]{ frame_dropped = true; }, []{}, []{});
 
     policy->swap_now_blocking();
     policy->swap_now_blocking();
@@ -184,3 +186,28 @@
     clock->advance_time(timeout + std::chrono::milliseconds{1});
     EXPECT_FALSE(frame_dropped);
 }
+
+TEST(TimeoutFrameDroppingPolicy, policy_calls_lock_unlock_functions)
+{
+    using namespace testing;
+
+    auto clock = std::make_shared<mt::FakeClock>();
+    auto timer = std::make_shared<mtd::FakeTimer>(clock);
+    std::chrono::milliseconds const timeout{1000};
+
+    mc::TimeoutFrameDroppingPolicyFactory factory{timer, timeout};
+
+    std::mutex m;
+    std::unique_lock<std::mutex> handler_guard{m, std::defer_lock};
+
+    auto policy = factory.create_policy([&]
+    {
+        EXPECT_THAT(handler_guard.owns_lock(), Eq(true));
+    },
+    [&] { handler_guard.lock(); },
+    [&] { handler_guard.unlock(); });
+
+
+    policy->swap_now_blocking();
+    clock->advance_time(timeout + std::chrono::milliseconds{1});
+}

=== modified file 'tests/unit-tests/graphics/android/test_platform.cpp'
--- tests/unit-tests/graphics/android/test_platform.cpp	2015-01-27 03:02:22 +0000
+++ tests/unit-tests/graphics/android/test_platform.cpp	2015-02-23 20:59:44 +0000
@@ -239,7 +239,7 @@
 
     ON_CALL(hwaccess, hw_get_module(_,_)).WillByDefault(Return(-1));
 
-    mir::SharedLibrary platform_lib{mtf::server_platform("graphics-android.so")};
+    mir::SharedLibrary platform_lib{mtf::server_platform("graphics-android")};
     auto probe = platform_lib.load_function<mg::PlatformProbe>(probe_platform);
     EXPECT_EQ(mg::PlatformPriority::unsupported, probe());
 }
@@ -248,7 +248,7 @@
 {
     testing::NiceMock<mtd::HardwareAccessMock> hwaccess;
 
-    mir::SharedLibrary platform_lib{mtf::server_platform("graphics-android.so")};
+    mir::SharedLibrary platform_lib{mtf::server_platform("graphics-android")};
     auto probe = platform_lib.load_function<mg::PlatformProbe>(probe_platform);
     EXPECT_EQ(mg::PlatformPriority::best, probe());
 }

=== modified file 'tests/unit-tests/graphics/mesa/test_platform.cpp'
--- tests/unit-tests/graphics/mesa/test_platform.cpp	2015-02-02 12:18:18 +0000
+++ tests/unit-tests/graphics/mesa/test_platform.cpp	2015-02-23 20:59:44 +0000
@@ -304,7 +304,7 @@
 {
     mtf::UdevEnvironment udev_environment;
 
-    mir::SharedLibrary platform_lib{mtf::server_platform("graphics-mesa.so")};
+    mir::SharedLibrary platform_lib{mtf::server_platform("graphics-mesa")};
     auto probe = platform_lib.load_function<mg::PlatformProbe>(probe_platform);
     EXPECT_EQ(mg::PlatformPriority::unsupported, probe());
 }
@@ -315,7 +315,7 @@
 
     udev_environment.add_standard_device("standard-drm-devices");
 
-    mir::SharedLibrary platform_lib{mtf::server_platform("graphics-mesa.so")};
+    mir::SharedLibrary platform_lib{mtf::server_platform("graphics-mesa")};
     auto probe = platform_lib.load_function<mg::PlatformProbe>(probe_platform);
     EXPECT_EQ(mg::PlatformPriority::best, probe());
 }

=== modified file 'tests/unit-tests/graphics/test_platform_prober.cpp'
--- tests/unit-tests/graphics/test_platform_prober.cpp	2014-12-17 19:59:21 +0000
+++ tests/unit-tests/graphics/test_platform_prober.cpp	2015-02-23 20:59:44 +0000
@@ -47,10 +47,10 @@
     std::vector<std::shared_ptr<mir::SharedLibrary>> modules;
 
 #ifdef MIR_BUILD_PLATFORM_MESA
-    modules.push_back(std::make_shared<mir::SharedLibrary>(mtf::server_platform("graphics-mesa.so")));
+    modules.push_back(std::make_shared<mir::SharedLibrary>(mtf::server_platform("graphics-mesa")));
 #endif
 #ifdef MIR_BUILD_PLATFORM_ANDROID
-    modules.push_back(std::make_shared<mir::SharedLibrary>(mtf::server_platform("graphics-android.so")));
+    modules.push_back(std::make_shared<mir::SharedLibrary>(mtf::server_platform("graphics-android")));
 #endif
     return modules;
 }

=== modified file 'tests/unit-tests/shared_library_test.cpp'
--- tests/unit-tests/shared_library_test.cpp	2015-01-27 03:02:22 +0000
+++ tests/unit-tests/shared_library_test.cpp	2015-02-23 20:59:44 +0000
@@ -59,7 +59,7 @@
 public:
     SharedLibrary()
         : nonexistent_library{"imma_totally_not_a_library"},
-          existing_library{mtf::client_platform("mesa.so")},
+          existing_library{mtf::client_platform("dummy.so")},
           nonexistent_function{"yo_dawg"},
           existing_function{"create_client_platform"},
           existent_version{"MIR_CLIENT_PLATFORM_2"},

=== added file 'tests/unit-tests/test_data/libinvalid.so.3'
=== modified file 'tests/unit-tests/test_glib_main_loop.cpp'
--- tests/unit-tests/test_glib_main_loop.cpp	2015-02-03 15:07:44 +0000
+++ tests/unit-tests/test_glib_main_loop.cpp	2015-02-23 20:59:44 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2014 Canonical Ltd.
+ * Copyright © 2014-2015 Canonical Ltd.
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 3 as
@@ -14,6 +14,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
+ *              Alberto Aguirre <alberto.aguirre@canonical.com>
  */
 
 #include "mir/glib_main_loop.h"
@@ -960,43 +961,45 @@
 }
 
 TEST_F(GLibMainLoopAlarmTest, alarm_callback_cannot_deadlock)
-{   // Regression test for deadlock bug LP: #1339700
-    std::timed_mutex m;
-    std::atomic_bool failed(false);
+{
+    using namespace testing;
+
+    std::mutex m;
+    std::unique_lock<std::mutex> handler_guard{m, std::defer_lock};
+    std::atomic_bool exit{false};
     int i = 0;
     int const loops = 5;
 
-    auto alarm = ml.notify_in(std::chrono::milliseconds{0}, [&]()
+    auto alarm = ml.create_alarm([&]()
     {
-        // From this angle, ensure we can lock m (alarm should be unlocked)
-        failed = !m.try_lock_for(std::chrono::seconds{5});
-        ASSERT_FALSE(failed);
+        //In this handler context, the alarm dispatcher should have
+        //acquired the handler guard
+        EXPECT_THAT(handler_guard.owns_lock(), Eq(true));
         ++i;
-        m.unlock();
+    },
+    [&] { handler_guard.lock(); },
+    [&] { handler_guard.unlock(); });
+
+    mt::AutoUnblockThread t([&]{ exit = true; }, [&]()
+    {
+        std::unique_lock<std::mutex> guard{m};
+        while (i < loops && !exit)
+        {
+            // It's safe to call cancel now because lock ordering is enforced
+            // by passing the lock/unlock lambdas to alarm above
+            alarm->cancel();
+            guard.unlock();
+            std::this_thread::yield();
+            guard.lock();
+        }
     });
 
-    std::thread t([&]()
-        {
-            m.lock();
-            while (i < loops && !failed)
-            {
-                // From this angle, ensure we can lock alarm while holding m
-                (void)alarm->state();
-                m.unlock();
-                std::this_thread::yield();
-                m.lock();
-            }
-            m.unlock();
-        });
-
     UnblockMainLoop unblocker(ml);
     for (int j = 0; j < loops; ++j)
     {
+        alarm->reschedule_in(std::chrono::milliseconds{10});
         clock->advance_by(std::chrono::milliseconds{11}, ml);
-        alarm->reschedule_in(std::chrono::milliseconds{10});
     }
-
-    t.join();
 }
 
 TEST_F(GLibMainLoopAlarmTest, alarm_fires_at_correct_time_point)

=== modified file 'tests/unit-tests/test_raii.cpp'
--- tests/unit-tests/test_raii.cpp	2013-10-21 14:21:00 +0000
+++ tests/unit-tests/test_raii.cpp	2015-02-23 20:59:44 +0000
@@ -179,3 +179,23 @@
 
     EXPECT_EQ(this, raii.get());
 }
+
+TEST_F(RaiiTest, paired_call_takes_std_function_refs)
+{
+    int creator_call_count = 0;
+    int deleter_call_count = 0;
+    int const expected_calls = 2;
+
+    std::function<void()> creator = [&creator_call_count] { creator_call_count++; };
+    std::function<void()> deleter = [&deleter_call_count] { deleter_call_count++; };
+
+    for (int i = 0; i < expected_calls; i++)
+    {
+        auto const raii = mir::raii::paired_calls(
+            std::ref(creator),
+            std::ref(deleter));
+    }
+
+    EXPECT_THAT(creator_call_count, Eq(expected_calls));
+    EXPECT_THAT(deleter_call_count, Eq(expected_calls));
+}

=== modified file 'tests/unit-tests/test_shared_library_prober.cpp'
--- tests/unit-tests/test_shared_library_prober.cpp	2015-01-21 07:34:50 +0000
+++ tests/unit-tests/test_shared_library_prober.cpp	2015-02-23 20:59:44 +0000
@@ -162,6 +162,7 @@
     EXPECT_CALL(report, loading_library(FilenameMatches("libarmhf.so")));
     EXPECT_CALL(report, loading_library(FilenameMatches("libi386.so")));
     EXPECT_CALL(report, loading_library(FilenameMatches("libarm64.so")));
+    EXPECT_CALL(report, loading_library(FilenameMatches("libinvalid.so.3")));
 
     mir::libraries_for_path(library_path, report);
 }
@@ -175,6 +176,7 @@
     bool amd64_failed{false};
     bool i386_failed{false};
     bool arm64_failed{false};
+    bool invalid_failed{false};
 
     ON_CALL(report, loading_failed(FilenameMatches("libamd64.so"), _))
             .WillByDefault(InvokeWithoutArgs([&amd64_failed]() { amd64_failed = true; }));
@@ -184,8 +186,11 @@
             .WillByDefault(InvokeWithoutArgs([&i386_failed]() { i386_failed = true; }));
     ON_CALL(report, loading_failed(FilenameMatches("libarm64.so"), _))
             .WillByDefault(InvokeWithoutArgs([&arm64_failed]() { arm64_failed = true; }));
+    ON_CALL(report, loading_failed(FilenameMatches("libinvalid.so.3"), _))
+            .WillByDefault(InvokeWithoutArgs([&invalid_failed]() { invalid_failed = true; }));
 
     mir::libraries_for_path(library_path, report);
 
+    EXPECT_TRUE(invalid_failed);
     EXPECT_TRUE(i386_failed || amd64_failed || armhf_failed || arm64_failed);
 }

