]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
http client fixes (curl based)
authorJaroslav Kysela <perex@perex.cz>
Wed, 9 Apr 2014 17:35:21 +0000 (19:35 +0200)
committerJaroslav Kysela <perex@perex.cz>
Mon, 5 May 2014 20:00:35 +0000 (22:00 +0200)
- check the private u64 value rather than fd (gdb problems)
- move the run call outside the connect routine (locking issues)
- try to fix more leaks (PR_Cleanup)

configure
src/http.h
src/http/http_client.c
src/main.c

index 3cd02ea319de5f070389423643a6aad2b2ae27c9..00d302a7f73c664ae7be92e1c0ef3937477b817f 100755 (executable)
--- a/configure
+++ b/configure
@@ -165,6 +165,9 @@ fi
 #
 if enabled_or_auto curl; then
   if check_pkg libcurl; then
+    if check_pkg nspr; then
+      enable nspr
+    fi
     enable curl
   elif enabled curl; then
     die "Curl development support not foun (use --disable-curl)"
index 120dda8fa03ec374eb254dd7822a7ccfd4c8b6c4..eb3264ce293dcfadbc2f20376cd239fe37bde980 100644 (file)
@@ -158,4 +158,6 @@ http_connect ( const url_t *url,
                void *p );
 void http_close ( http_client_t *hc );
 
+void curl_done ( void );
+
 #endif /* HTTP_H_ */
index 84b64c9c3208aaa9b80e0b4b7234e8c08e71b553..3cba6459421f99493add5caa56c1d2cafa2116b7 100644 (file)
@@ -31,6 +31,7 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <signal.h>
+#include <fcntl.h>
 
 
 /*
@@ -41,6 +42,7 @@ struct http_client
   CURL *hc_curl;
   int   hc_fd;
   url_t hc_url;
+  int   hc_init;
   int   hc_begin;
 
   /* Callbacks */
@@ -55,10 +57,12 @@ struct http_client
 /*
  * Global state
  */
+static int                      http_running;
 static tvhpoll_t               *http_poll;
 static TAILQ_HEAD(,http_client) http_clients;
 static pthread_mutex_t          http_lock;
 static CURLM                   *http_curlm;
+static th_pipe_t                http_pipe;
 
 /*
  * Disable
@@ -109,6 +113,7 @@ http_curl_socket ( CURL *c, int fd, int a, void *u, void *s )
     if (a & CURL_POLL_OUT)
       ev.events |= TVHPOLL_OUT;
     ev.data.fd = fd;
+    ev.data.u64 = (uint64_t)hc;
     hc->hc_fd  = fd;
     tvhpoll_add(http_poll, &ev, 1);
   }
@@ -138,27 +143,41 @@ http_curl_data ( void *buf, size_t len, size_t n, void *p )
 static void *
 http_thread ( void *p )
 {
-  int n, e, run = 0;
+  int n, run = 0;
   tvhpoll_event_t ev;
   http_client_t *hc;
+  char c;
 
-  while (tvheadend_running) {
+  while (http_running) {
     n = tvhpoll_wait(http_poll, &ev, 1, -1);
     if (n < 0) {
       if (tvheadend_running)
         tvherror("http_client", "tvhpoll_wait() error");
-      break;
-    } else {
+    } else if (n > 0) {
+      if ((uint64_t)&http_pipe == ev.data.u64) {
+        if (read(http_pipe.rd, &c, 1) == 1) {
+          if (c == 'n') {
+            pthread_mutex_lock(&http_lock);
+            TAILQ_FOREACH(hc, &http_clients, hc_link) {
+              if (hc->hc_init == 0)
+                continue;
+              hc->hc_init = 0;
+              curl_multi_socket_action(http_curlm, hc->hc_fd, 0, &run);
+            }
+            pthread_mutex_unlock(&http_lock);
+          } else {
+            /* end-of-task */
+            break;
+          }
+        }
+        continue;
+      }
       pthread_mutex_lock(&http_lock);
       TAILQ_FOREACH(hc, &http_clients, hc_link)
-        if (hc->hc_fd == ev.data.fd)
+        if ((uint64_t)hc == ev.data.u64)
           break;
-      if (hc && (ev.events & (TVHPOLL_IN | TVHPOLL_OUT))) {
-        e = 0;
-        if (ev.events & TVHPOLL_IN)  e |= CURL_POLL_IN;
-        if (ev.events & TVHPOLL_OUT) e |= CURL_POLL_OUT;
-        curl_multi_socket_action(http_curlm, ev.data.fd, 0, &run);
-      }
+      if (hc && (ev.events & (TVHPOLL_IN | TVHPOLL_OUT)))
+        curl_multi_socket_action(http_curlm, hc->hc_fd, 0, &run);
       pthread_mutex_unlock(&http_lock);
     }
   }
@@ -177,8 +196,6 @@ http_connect
     http_client_fail_cb fail_cb, 
     void *p )
 {
-  int run;
-
   /* Setup structure */
   http_client_t *hc = calloc(1, sizeof(http_client_t));
   hc->hc_curl       = curl_easy_init();
@@ -187,6 +204,7 @@ http_connect
   hc->hc_data       = data_cb;
   hc->hc_fail       = fail_cb;
   hc->hc_opaque     = p;
+  hc->hc_init       = 1;
 
   /* Store */
   pthread_mutex_lock(&http_lock);
@@ -198,9 +216,10 @@ http_connect
   curl_easy_setopt(hc->hc_curl, CURLOPT_WRITEFUNCTION, http_curl_data);
   curl_easy_setopt(hc->hc_curl, CURLOPT_WRITEDATA,     hc);
   curl_multi_add_handle(http_curlm, hc->hc_curl);
-  curl_multi_socket_action(http_curlm, CURL_SOCKET_TIMEOUT, 0, &run);
   pthread_mutex_unlock(&http_lock);
 
+  tvh_write(http_pipe.wr, "n", 1);
+
   return hc;
 }
 
@@ -224,6 +243,8 @@ pthread_t http_client_tid;
 void
 http_client_init ( void )
 {
+  tvhpoll_event_t ev = { 0 };
+
   /* Setup list */
   pthread_mutex_init(&http_lock, NULL);
   TAILQ_INIT(&http_clients);
@@ -233,21 +254,48 @@ http_client_init ( void )
   http_curlm = curl_multi_init();
   curl_multi_setopt(http_curlm, CURLMOPT_SOCKETFUNCTION, http_curl_socket);
 
+  /* Setup pipe */
+  tvh_pipe(O_NONBLOCK, &http_pipe);
+
   /* Setup poll */
-  http_poll = tvhpoll_create(10);
+  http_poll   = tvhpoll_create(10);
+  ev.fd       = http_pipe.rd;
+  ev.events   = TVHPOLL_IN;
+  ev.data.u64 = (uint64_t)&http_pipe;
+  tvhpoll_add(http_poll, &ev, 1);
 
   /* Setup thread */
+  http_running = 1;
   tvhthread_create(&http_client_tid, NULL, http_thread, NULL, 0);
 }
 
 void
 http_client_done ( void )
 {
-  pthread_kill(http_client_tid, SIGTERM);
+  http_running = 0;
+  tvh_write(http_pipe.wr, "", 1);
   pthread_join(http_client_tid, NULL);
+  assert(TAILQ_FIRST(&http_clients) == NULL);
+  tvh_pipe_close(&http_pipe);
   tvhpoll_destroy(http_poll);
   curl_multi_cleanup(http_curlm);
+}
+
+
+void
+curl_done ( void )
+{
+#if ENABLE_NSPR
+  void PR_Cleanup( void );
+#endif
   curl_global_cleanup();
+#if ENABLE_NSPR
+  /*
+   * Note: Curl depends on the NSPR library.
+   *       The PR_Cleanup() call is mandatory to free NSPR resources.
+   */
+  PR_Cleanup();
+#endif
 }
 
 #else /* ENABLE_CURL */
@@ -262,4 +310,9 @@ http_client_done ( void )
 {
 }
 
+void
+curl_done ( void )
+{
+}
+
 #endif /* ENABLE_CURL */
index 2245ecde72535de1dd6b112fc1494892b529235c..534e99ccd34491d791ac9551cdd976a99c1a170e 100644 (file)
@@ -748,6 +748,8 @@ main(int argc, char **argv)
 
   imagecache_init();
 
+  http_client_init();
+
   service_init();
 
 #if ENABLE_MPEGTS
@@ -764,7 +766,6 @@ main(int argc, char **argv)
   timeshift_init();
 #endif
 
-  http_client_init();
   tcp_server_init(opt_ipv6);
   http_server_init(opt_bindaddr);
   webui_init();
@@ -823,11 +824,11 @@ main(int argc, char **argv)
   tvhftrace("main", htsp_done);
   tvhftrace("main", http_server_done);
   tvhftrace("main", webui_done);
-  tvhftrace("main", http_client_done);
   tvhftrace("main", fsmonitor_done);
 #if ENABLE_MPEGTS
   tvhftrace("main", mpegts_done);
 #endif
+  tvhftrace("main", http_client_done);
 
   // Note: the locking is obviously a bit redundant, but without
   //       we need to disable the gtimer_arm call in epg_save()
@@ -867,6 +868,8 @@ main(int argc, char **argv)
     
   free(opt_tsfile.str);
 
+  curl_done();
+
   return 0;
 }