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()); }
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()); }