TEST(ServerShutdownWithThreadException,
     server_releases_resources_on_abnormal_input_thread_termination)
{
    auto server_config = std::make_shared<mtf::FakeInputServerConfiguration>();

    std::thread server{
        [&server_config]
        {
            EXPECT_THROW(
                mir::run_mir(*server_config, [](mir::DisplayServer&){}),
                std::runtime_error);
        }};

    {
        auto dev = mtf::add_fake_input_device(mir::input::InputDeviceInfo{"throwing device", "throwing-device-0",
                                                                          mir::input::DeviceCapability::unknown});
        dev->emit_runtime_error();
        server.join();
        dev.reset();
    }

    std::weak_ptr<mir::graphics::Display> display = server_config->the_display();
    std::weak_ptr<mir::compositor::Compositor> compositor = server_config->the_compositor();
    std::weak_ptr<mir::frontend::Connector> connector = server_config->the_connector();
    std::weak_ptr<mi::InputManager> input_manager = server_config->the_input_manager();
    std::weak_ptr<mi::InputDeviceHub> hub = server_config->the_input_device_hub();

    server_config.reset();

    EXPECT_EQ(0, display.use_count());
    EXPECT_EQ(0, compositor.use_count());
    EXPECT_EQ(0, connector.use_count());
    EXPECT_EQ(0, input_manager.use_count());
    EXPECT_EQ(0, hub.use_count());
    }
示例#2
0
std::shared_ptr<mi::InputManager> mtf::TestingServerConfiguration::the_input_manager()
{
    auto options = the_options();
    if (options->get("tests-use-real-input", false))
        return mi::create_input_manager(the_event_filters(), the_display());
    else
        return std::make_shared<StubInputManager>();
}
std::shared_ptr<mi::InputRegion> mir::DefaultServerConfiguration::the_input_region()
{
    return input_region(
        [this]()
        {
            return std::make_shared<mi::DisplayInputRegion>(the_display());
        });
}
std::shared_ptr<ms::PixelBuffer>
mir::DefaultServerConfiguration::the_pixel_buffer()
{
    return pixel_buffer(
        [this]()
        {
            return std::make_shared<ms::GLPixelBuffer>(
                the_display()->create_gl_context());
        });
}
std::shared_ptr<ms::MediatingDisplayChanger>
mir::DefaultServerConfiguration::the_mediating_display_changer()
{
    return mediating_display_changer(
        [this]()
        {
            return std::make_shared<ms::MediatingDisplayChanger>(
                the_display(),
                the_compositor(),
                the_display_configuration_policy(),
                the_session_container(),
                the_session_event_handler_register(),
                the_server_action_queue(),
                the_display_configuration_report());
        });

}
std::shared_ptr<ms::SessionCoordinator>
mir::DefaultServerConfiguration::the_session_coordinator()
{
    return session_coordinator(
        [this]()
        {
            return std::make_shared<ms::SessionManager>(
                    the_surface_coordinator(),
                    the_surface_factory(),
                    the_buffer_stream_factory(),
                    the_session_container(),
                    the_snapshot_strategy(),
                    the_session_event_sink(),
                    the_session_listener(),
                    the_display(),
                    the_application_not_responding_detector());
        });
}
TEST(ServerShutdownWithThreadException,
     server_releases_resources_on_abnormal_compositor_thread_termination)
{
    struct ServerConfig : mtf::TestingServerConfiguration
    {
        std::shared_ptr<mc::DisplayBufferCompositorFactory>
            the_display_buffer_compositor_factory() override
        {
            return display_buffer_compositor_factory(
                [this]()
                {
                    return std::make_shared<ExceptionThrowingDisplayBufferCompositorFactory>();
                });
        }
    };

    auto server_config = std::make_shared<ServerConfig>();

    std::thread server{
        [&]
        {
            EXPECT_THROW(
                mir::run_mir(*server_config, [](mir::DisplayServer&){}),
                std::runtime_error);
        }};

    server.join();

    std::weak_ptr<mir::graphics::Display> display = server_config->the_display();
    std::weak_ptr<mir::compositor::Compositor> compositor = server_config->the_compositor();
    std::weak_ptr<mir::frontend::Connector> connector = server_config->the_connector();
    std::weak_ptr<mi::InputManager> input_manager = server_config->the_input_manager();
    std::weak_ptr<mi::InputDeviceHub> hub = server_config->the_input_device_hub();

    server_config.reset();

    EXPECT_EQ(0, display.use_count());
    EXPECT_EQ(0, compositor.use_count());
    EXPECT_EQ(0, connector.use_count());
    EXPECT_EQ(0, input_manager.use_count());
    EXPECT_EQ(0, hub.use_count());
}
// This also acts as a regression test for LP: #1378740
TEST(ServerShutdownWithThreadException,
     server_releases_resources_on_abnormal_main_thread_termination)
{
    // Use the FakeInputServerConfiguration to get the production input components
    auto server_config = std::make_shared<mtf::FakeInputServerConfiguration>();

    std::thread server{
        [&]
        {
            EXPECT_THROW(
                mir::run_mir(*server_config,
                    [server_config](mir::DisplayServer&)
                    {
                        server_config->the_main_loop()->enqueue(
                            server_config.get(),
                            [] { throw std::runtime_error(""); });
                    }),
                std::runtime_error);
        }};

    server.join();

    std::weak_ptr<mir::graphics::Display> display = server_config->the_display();
    std::weak_ptr<mir::compositor::Compositor> compositor = server_config->the_compositor();
    std::weak_ptr<mir::frontend::Connector> connector = server_config->the_connector();
    std::weak_ptr<mi::InputManager> input_manager = server_config->the_input_manager();
    std::weak_ptr<mi::InputDeviceHub> hub = server_config->the_input_device_hub();

    server_config.reset();

    EXPECT_EQ(0, display.use_count());
    EXPECT_EQ(0, compositor.use_count());
    EXPECT_EQ(0, connector.use_count());
    EXPECT_EQ(0, input_manager.use_count());
    EXPECT_EQ(0, hub.use_count());
}