]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
subscription: fix double list insertion on detection of bad service
authorAdam Sutton <dev@adamsutton.me.uk>
Wed, 11 Sep 2013 21:12:40 +0000 (22:12 +0100)
committerAdam Sutton <dev@adamsutton.me.uk>
Wed, 11 Sep 2013 21:12:40 +0000 (22:12 +0100)
If a service was marked as bad (no input) it was not unlinking the
subscription from the service before re-applying, this resulted in
a double entry into the service subs list and ultimatey a livelock
or possibly worse.

src/subscriptions.c

index 7ad7766f48cf91b72ced0b85cead94bf3e6a923d..323a94467594aab2067606e5b3c029b27934e240 100644 (file)
@@ -108,8 +108,8 @@ subscription_link_service(th_subscription_t *s, service_t *t)
 /**
  * Called from service code
  */
-void
-subscription_unlink_service(th_subscription_t *s, int reason)
+static void
+subscription_unlink_service0(th_subscription_t *s, int reason, int stop)
 {
   streaming_message_t *sm;
   service_t *t = s->ths_service;
@@ -118,10 +118,10 @@ subscription_unlink_service(th_subscription_t *s, int reason)
 
   pthread_mutex_lock(&t->s_stream_mutex);
 
-  // Unlink from service output
   streaming_target_disconnect(&t->s_streaming_pad, &s->ths_input);
 
-  if(TAILQ_FIRST(&t->s_components) != NULL && 
+  if(stop &&
+     TAILQ_FIRST(&t->s_components) != NULL && 
      s->ths_state == SUBSCRIPTION_GOT_SERVICE) {
     // Send a STOP message to the subscription client
     sm = streaming_msg_create_code(SMT_STOP, reason);
@@ -134,6 +134,12 @@ subscription_unlink_service(th_subscription_t *s, int reason)
   s->ths_service = NULL;
 }
 
+void
+subscription_unlink_service(th_subscription_t *s, int reason)
+{
+  subscription_unlink_service0(s, reason, 1);
+}
+
 /*
  * Called from mpegts code
  */
@@ -209,11 +215,14 @@ subscription_reschedule(void)
       if(s->ths_state != SUBSCRIPTION_BAD_SERVICE)
              continue; /* And it not bad, so we're happy */
 
+      subscription_unlink_service0(s, SM_CODE_BAD_SOURCE, 0);
+
       si = s->ths_current_instance;
 
       assert(si != NULL);
       si->si_error = s->ths_testing_error;
       time(&si->si_error_time);
+  
     }
 
     if (s->ths_channel)