]> granicus.if.org Git - curl/commitdiff
asyn-thread: Fixed cleanup after OOM
authorDan Fandrich <dan@coneharvesters.com>
Mon, 28 Aug 2017 22:30:30 +0000 (00:30 +0200)
committerDan Fandrich <dan@coneharvesters.com>
Mon, 28 Aug 2017 22:35:19 +0000 (00:35 +0200)
destroy_async_data() assumes that if the flag "done" is not set yet, the
thread itself will clean up once the request is complete.  But if an
error (generally OOM) occurs before the thread even has a chance to
start, it will never get a chance to clean up and memory will be leaked.
By clearing "done" only just before starting the thread, the correct
cleanup sequence will happen in all cases.

lib/asyn-thread.c

index c9f4431675d8c11274cf9cf02285729c4e11d7bd..a86772965396d2630443a8379637c443350614a8 100644 (file)
@@ -210,6 +210,10 @@ int init_thread_sync_data(struct thread_data * td,
 
   tsd->td = td;
   tsd->port = port;
+  /* Treat the request as done until the thread actually starts so any early
+   * cleanup gets done properly.
+   */
+  tsd->done = 1;
 #ifdef HAVE_GETADDRINFO
   DEBUGASSERT(hints);
   tsd->hints = *hints;
@@ -403,6 +407,9 @@ static bool init_resolve_thread(struct connectdata *conn,
   if(!conn->async.hostname)
     goto err_exit;
 
+  /* The thread will set this to 1 when complete. */
+  td->tsd.done = 0;
+
 #ifdef HAVE_GETADDRINFO
   td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);
 #else
@@ -410,6 +417,8 @@ static bool init_resolve_thread(struct connectdata *conn,
 #endif
 
   if(!td->thread_hnd) {
+    /* The thread never started, so mark it as done here for proper cleanup. */
+    td->tsd.done = 1;
     err = errno;
     goto err_exit;
   }