summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorFrank Schmirler <vdr@schmirler.de>2011-10-18 08:50:54 +0200
committerFrank Schmirler <vdr@schmirler.de>2011-10-18 08:50:54 +0200
commit615f101b9dce6ae4a2b7b02866176a413e47169f (patch)
treec0bb6929e51b0d1c6e00274e0ffdbe0888dd88ee /server
parent2fae067cfef6f930415e8b3d4c4713b5de91b1eb (diff)
downloadvdr-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.c2
-rw-r--r--server/connectionIGMP.c63
-rw-r--r--server/connectionIGMP.h4
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 */