~ricmm/media-hub/keep-display-recording-1362658

« back to all changes in this revision

Viewing changes to src/core/media/service_implementation.cpp

  • Committer: CI bot
  • Author(s): Alberto Aguirre
  • Date: 2014-09-26 04:05:52 UTC
  • mfrom: (67.2.4 fix-1371454)
  • Revision ID: ps-jenkins@lists.canonical.com-20140926040552-gv0u67kopamnd5qy
Fix self deadlock when clients disconnect from media::Player

When receiving a media::PlayerImplementation on_client_disconnected signal, avoid calling
remove_player_for_key within the same context as the player object may be deleted (which owns
the signal object whose destructor waits until all slots are dispatched). Fixes: 1371454
Approved by: Jim Hodapp, Thomas Voß

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
#include "player_configuration.h"
24
24
#include "player_implementation.h"
25
25
 
 
26
#include <boost/asio.hpp>
 
27
 
26
28
#include <cstdint>
27
29
#include <map>
28
30
#include <memory>
35
37
struct media::ServiceImplementation::Private
36
38
{
37
39
    Private()
38
 
        : resume_key(std::numeric_limits<std::uint32_t>::max())
 
40
        : resume_key(std::numeric_limits<std::uint32_t>::max()),
 
41
          keep_alive(io_service)
39
42
    {
40
43
        bus = std::shared_ptr<dbus::Bus>(new dbus::Bus(core::dbus::WellKnownBus::session));
41
 
        bus->install_executor(dbus::asio::make_executor(bus));
 
44
        bus->install_executor(dbus::asio::make_executor(bus, io_service));
42
45
        worker = std::move(std::thread([this]()
43
46
        {
44
47
            bus->run();
65
68
    media::Player::PlayerKey resume_key;
66
69
    std::thread worker;
67
70
    dbus::Bus::Ptr bus;
 
71
    boost::asio::io_service io_service;
 
72
    boost::asio::io_service::work keep_alive;
68
73
    std::shared_ptr<dbus::Object> indicator_power_session;
69
74
    std::shared_ptr<core::dbus::Property<core::IndicatorPower::PowerLevel>> power_level;
70
75
    std::shared_ptr<core::dbus::Property<core::IndicatorPower::IsWarning>> is_warning;
104
109
    auto key = conf.key;
105
110
    player->on_client_disconnected().connect([this, key]()
106
111
    {
107
 
        remove_player_for_key(key);
 
112
        // Call remove_player_for_key asynchronously otherwise deadlock can occur
 
113
        // if called within this dispatcher context.
 
114
        // remove_player_for_key can destroy the player instance which in turn
 
115
        // destroys the "on_client_disconnected" signal whose destructor will wait
 
116
        // until all dispatches are done
 
117
        d->io_service.post([this, key]()
 
118
        {
 
119
            remove_player_for_key(key);
 
120
        });
108
121
    });
109
122
 
110
123
    return player;