]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
http client: add refcounting for callbacks
authorJaroslav Kysela <perex@perex.cz>
Wed, 7 Dec 2016 09:44:07 +0000 (10:44 +0100)
committerJaroslav Kysela <perex@perex.cz>
Wed, 7 Dec 2016 09:44:59 +0000 (10:44 +0100)
src/http.h
src/httpc.c

index b929daa6c7596670089f4b842bc22f7f536417d0..65ac665ec3fb1c883c77e957a87f8470ed1b7418 100644 (file)
@@ -316,6 +316,7 @@ struct http_client {
   char        *hc_location;
   uint8_t      hc_running;     /* outside hc_mutex */
   uint8_t      hc_shutdown_wait;/* outside hc_mutex */
+  int          hc_refcnt;       /* callback protection - outside hc_mutex */
   int          hc_redirects;
   int          hc_result;
   int          hc_shutdown:1;
index df7997c3eacdc38706be333c31cf6d1c6ab39579..cb813040b668d07a4ca1719dedef416850bb4565 100644 (file)
@@ -63,7 +63,6 @@ struct http_client_ssl {
   size_t   wbio_pos;
 };
 
-
 static int
 http_client_redirected ( http_client_t *hc );
 static int
@@ -77,7 +76,6 @@ static void
 http_client_testsuite_run( void );
 #endif
 
-
 /*
  * Global state
  */
@@ -98,6 +96,27 @@ shortid( http_client_t *hc )
   return hc->hc_id;
 }
 
+/*
+ *
+ */
+static void
+http_client_get( http_client_t *hc )
+{
+  hc->hc_refcnt++;
+}
+
+static void
+http_client_put( http_client_t *hc )
+{
+  hc->hc_refcnt--;
+}
+
+static int
+http_client_busy( http_client_t *hc )
+{
+  return !!hc->hc_refcnt;
+}
+
 /*
  *
  */
@@ -154,9 +173,11 @@ http_client_shutdown ( http_client_t *hc, int force, int reconnect )
   }
   if (hc->hc_fd >= 0) {
     if (hc->hc_conn_closed) {
+      http_client_get(hc);
       pthread_mutex_unlock(&hc->hc_mutex);
       hc->hc_conn_closed(hc, -hc->hc_result);
       pthread_mutex_lock(&hc->hc_mutex);
+      http_client_put(hc);
     }
     if (hc->hc_fd >= 0)
       close(hc->hc_fd);
@@ -670,15 +691,19 @@ http_client_finish( http_client_t *hc )
   tvhtrace(LS_HTTPC, "%04X: finishing", shortid(hc));
 
   if (hc->hc_in_rtp_data && hc->hc_rtp_data_complete) {
+    http_client_get(hc);
     pthread_mutex_unlock(&hc->hc_mutex);
     res = hc->hc_rtp_data_complete(hc);
     pthread_mutex_lock(&hc->hc_mutex);
+    http_client_put(hc);
     if (res < 0)
       return http_client_flush(hc, res);
   } else if (hc->hc_data_complete) {
+    http_client_get(hc);
     pthread_mutex_unlock(&hc->hc_mutex);
     res = hc->hc_data_complete(hc);
     pthread_mutex_lock(&hc->hc_mutex);
+    http_client_put(hc);
     if (res < 0)
       return http_client_flush(hc, res);
   }
@@ -742,9 +767,11 @@ http_client_data_copy( http_client_t *hc, char *buf, size_t len )
   int res;
 
   if (hc->hc_data_received) {
+    http_client_get(hc);
     pthread_mutex_unlock(&hc->hc_mutex);
     res = hc->hc_data_received(hc, buf, len);
     pthread_mutex_lock(&hc->hc_mutex);
+    http_client_put(hc);
     if (res < 0)
       return res;
   } else {
@@ -1065,9 +1092,11 @@ header:
   if (p)
     hc->hc_chunked = strcasecmp(p, "chunked") == 0;
   if (hc->hc_hdr_received) {
+    http_client_get(hc);
     pthread_mutex_unlock(&hc->hc_mutex);
     res = hc->hc_hdr_received(hc);
     pthread_mutex_lock(&hc->hc_mutex);
+    http_client_put(hc);
     if (res < 0)
       return http_client_flush(hc, res);
   }
@@ -1113,9 +1142,11 @@ rtsp_data:
       return HTTP_CON_RECEIVING;
     }
     if (hc->hc_rtp_data_received) {
+      http_client_get(hc);
       pthread_mutex_unlock(&hc->hc_mutex);
       res = hc->hc_rtp_data_received(hc, hc->hc_rbuf + r, hc->hc_csize);
       pthread_mutex_lock(&hc->hc_mutex);
+      http_client_put(hc);
       if (res < 0)
         return res;
     } else {
@@ -1251,6 +1282,8 @@ http_client_simple_reconnect ( http_client_t *hc, const url_t *u,
   tvhpoll_t *efd;
   int r;
 
+  lock_assert(&hc->hc_mutex);
+
   if (u->scheme == NULL || u->scheme[0] == '\0' ||
       u->host == NULL || u->host[0] == '\0' ||
       u->port < 0) {
@@ -1320,8 +1353,6 @@ http_client_redirected ( http_client_t *hc )
     free(location);
     return -EIO;
   }
-  free(hc->hc_url);
-  hc->hc_url = u.raw ? strdup(u.raw) : NULL;
   free(location);
 
   r = http_client_simple_reconnect(hc, &u, hc->hc_redirv);
@@ -1598,6 +1629,11 @@ http_client_close ( http_client_t *hc )
     pthread_mutex_unlock(&http_lock);
   }
   pthread_mutex_lock(&hc->hc_mutex);
+  while (http_client_busy(hc)) {
+    pthread_mutex_unlock(&hc->hc_mutex);
+    tvh_safe_usleep(10000);
+    pthread_mutex_lock(&hc->hc_mutex);
+  }
   http_client_shutdown(hc, 1, 0);
   http_client_flush(hc, 0);
   tvhtrace(LS_HTTPC, "%04X: Closed", shortid(hc));