diff options
author | Frank Schmirler <vdr@schmirler.de> | 2011-10-18 08:50:54 +0200 |
---|---|---|
committer | Frank Schmirler <vdr@schmirler.de> | 2011-10-18 08:50:54 +0200 |
commit | 615f101b9dce6ae4a2b7b02866176a413e47169f (patch) | |
tree | c0bb6929e51b0d1c6e00274e0ffdbe0888dd88ee /server | |
parent | 2fae067cfef6f930415e8b3d4c4713b5de91b1eb (diff) | |
download | vdr-plugin-streamdev-615f101b9dce6ae4a2b7b02866176a413e47169f.tar.gz vdr-plugin-streamdev-615f101b9dce6ae4a2b7b02866176a413e47169f.tar.bz2 |
fixed regression of "live TV must be switched in VDR main thread" change:
deadlock in IGMP streaming server when switching live TV.
Previously cComponentIGMP::Accept did all the work including the channel
switch with the new cConnectionIGMP waiting for MainThreadHook. But as the
new connection is stored *after* Accept, MainThreadHook didn't see it and
so wasn't able to switch. The streamdev main thread waited forever.
Moved the main work into cComponentIGMP::Welcome.
Diffstat (limited to 'server')
-rw-r--r-- | server/componentIGMP.c | 2 | ||||
-rw-r--r-- | server/connectionIGMP.c | 63 | ||||
-rw-r--r-- | server/connectionIGMP.h | 4 |
3 files changed, 39 insertions, 30 deletions
diff --git a/server/componentIGMP.c b/server/componentIGMP.c index d9f8811..9ad7d30 100644 --- a/server/componentIGMP.c +++ b/server/componentIGMP.c @@ -434,7 +434,7 @@ void cComponentIGMP::IGMPStartMulticast(cMulticastGroup* Group) if (g > MULTICAST_PRIV_MIN && g <= MULTICAST_PRIV_MAX) { cChannel *channel = Channels.GetByNumber(g - MULTICAST_PRIV_MIN); Group->connection = (cConnectionIGMP*) NewClient(); - if (!Group->connection->Start(channel, Group->group)) { + if (!Group->connection->SetChannel(channel, Group->group)) { DELETENULL(Group->connection); } } diff --git a/server/connectionIGMP.c b/server/connectionIGMP.c index 708f41c..53b9acf 100644 --- a/server/connectionIGMP.c +++ b/server/connectionIGMP.c @@ -13,7 +13,8 @@ cConnectionIGMP::cConnectionIGMP(const char* Name, int ClientPort, eStreamType S cServerConnection(Name, SOCK_DGRAM), m_LiveStreamer(NULL), m_ClientPort(ClientPort), - m_StreamType(StreamType) + m_StreamType(StreamType), + m_Channel(NULL) { } @@ -22,41 +23,47 @@ cConnectionIGMP::~cConnectionIGMP() delete m_LiveStreamer; } -bool cConnectionIGMP::Start(cChannel *Channel, in_addr_t Dst) +bool cConnectionIGMP::SetChannel(cChannel *Channel, in_addr_t Dst) { - if (Channel != NULL) { - cDevice *device = NULL; - if (ProvidesChannel(Channel, 0)) - device = GetDevice(Channel, 0); - if (device != NULL) { - device->SwitchChannel(Channel, false); - struct in_addr ip; - ip.s_addr = Dst; - if (Connect(inet_ntoa(ip), m_ClientPort)) { - m_LiveStreamer = new cStreamdevLiveStreamer(0, this); - if (m_LiveStreamer->SetChannel(Channel, m_StreamType)) { - m_LiveStreamer->SetDevice(device); - if (!SetDSCP()) - LOG_ERROR_STR("unable to set DSCP sockopt"); - Dprintf("streamer start\n"); - m_LiveStreamer->Start(this); - return true; - } - else - esyslog("streamdev-server IGMP: SetDevice failed"); - DELETENULL(m_LiveStreamer); - } - else - esyslog("streamdev-server IGMP: Connect failed: %m"); - } + if (Channel) { + m_Channel = Channel; + struct in_addr ip; + ip.s_addr = Dst; + if (Connect(inet_ntoa(ip), m_ClientPort)) + return true; else - esyslog("streamdev-server IGMP: GetDevice failed"); + esyslog("streamdev-server IGMP: Connect failed: %m"); + return false; } else esyslog("streamdev-server IGMP: Channel not found"); return false; } +void cConnectionIGMP::Welcome() +{ + cDevice *device = NULL; + if (ProvidesChannel(m_Channel, 0)) + device = GetDevice(m_Channel, 0); + if (device != NULL) { + device->SwitchChannel(m_Channel, false); + m_LiveStreamer = new cStreamdevLiveStreamer(0, this); + if (m_LiveStreamer->SetChannel(m_Channel, m_StreamType)) { + m_LiveStreamer->SetDevice(device); + if (!SetDSCP()) + LOG_ERROR_STR("unable to set DSCP sockopt"); + Dprintf("streamer start\n"); + m_LiveStreamer->Start(this); + } + else { + esyslog("streamdev-server IGMP: SetChannel failed"); + DELETENULL(m_LiveStreamer); + } + } + else + esyslog("streamdev-server IGMP: GetDevice failed"); +} + void cConnectionIGMP::Stop() { if (m_LiveStreamer) { diff --git a/server/connectionIGMP.h b/server/connectionIGMP.h index 90abd58..facda65 100644 --- a/server/connectionIGMP.h +++ b/server/connectionIGMP.h @@ -20,12 +20,14 @@ private: cStreamdevLiveStreamer *m_LiveStreamer; int m_ClientPort; eStreamType m_StreamType; + cChannel *m_Channel; public: cConnectionIGMP(const char* Name, int ClientPort, eStreamType StreamType); virtual ~cConnectionIGMP(); - bool Start(cChannel *Channel, in_addr_t Dst); + bool SetChannel(cChannel *Channel, in_addr_t Dst); + virtual void Welcome(void); void Stop(); /* Not used here */ |