]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tidy-up: prefer `return` over `exit()`, fix fallouts
authorViktor Szakats <commit@vsz.me>
Thu, 27 Feb 2025 10:32:43 +0000 (11:32 +0100)
committerViktor Szakats <commit@vsz.me>
Fri, 28 Feb 2025 12:11:41 +0000 (13:11 +0100)
To avoid breaking the control flow and align to majority of code
already using `return`.

`exit()` has the side-effect of suppressing leak detection in cases.
Fix fallouts detected after switching to `return`.

- configure:
  - fix `getaddrinfo` run test to call `freeaddrinfo()` to pacify ASAN,
    and call `WSACleanup()` to deinit winsock2.
  - fix `getifaddrs` run test to call `freeifaddrs()` to pacify ASAN.
- tests/server:
  - setup `atexit(win32_cleanup)` via `win32_init()`.
  - return 2 instead of 1 on winsock2 init failures.
  - sws: goto cleanup instead of `exit()` in `http_connect()`.
    Follow-up to 02dfe7193704817184b522888ffa926e6b73f648 #7235
- tests/client/http:
  - cleanup memory to pacify ASAN in `h2-upgrade-extreme`,
    `tls-session-reuse`.
- examples:
  - block_ip: fix memory leak reported by CI.
  - http2-upload: avoid handle leaks.

Untouched `exit()` calls, made from callbacks:
- docs/examples: ephiperfifo.c, ghiper.c, hiperfifo.c
- tests/libtest: lib582.c, lib655.c, lib670.c
- tests/server: tftpd.c

Closes #16507

22 files changed:
docs/examples/block_ip.c
docs/examples/chkspeed.c
docs/examples/cookie_interface.c
docs/examples/htmltitle.cpp
docs/examples/http2-download.c
docs/examples/http2-upload.c
m4/curl-compilers.m4
m4/curl-functions.m4
packages/vms/report_openssl_version.c
tests/http/clients/h2-pausing.c
tests/http/clients/h2-upgrade-extreme.c
tests/http/clients/tls-session-reuse.c
tests/http/clients/upload-pausing.c
tests/server/mqttd.c
tests/server/resolve.c
tests/server/rtspd.c
tests/server/sockfilt.c
tests/server/socksd.c
tests/server/sws.c
tests/server/tftpd.c
tests/server/util.c
tests/server/util.h

index b185177ab68c3c0935b507595128a810b2f8e1a4..9a1c0222e88b0b3fbbefc31fdbb701492a1a4c0f 100644 (file)
@@ -298,14 +298,19 @@ int main(void)
 
   filter = (struct connection_filter *)calloc(1, sizeof(*filter));
   if(!filter)
-    exit(1);
+    return 1;
 
-  if(curl_global_init(CURL_GLOBAL_DEFAULT))
-    exit(1);
+  if(curl_global_init(CURL_GLOBAL_DEFAULT)) {
+    free(filter);
+    return 1;
+  }
 
   curl = curl_easy_init();
-  if(!curl)
-    exit(1);
+  if(!curl) {
+    curl_global_cleanup();
+    free(filter);
+    return 1;
+  }
 
   /* Set the target URL */
   curl_easy_setopt(curl, CURLOPT_URL, "http://localhost");
index 687b264b9bb2475e79a2060ed594e95f2725d6c4..fc40814696a6d7bac176992837268189d9d4bd84 100644 (file)
@@ -79,12 +79,12 @@ int main(int argc, char *argv[])
           fprintf(stderr,
                   "\rUsage: %s [-m=1|2|5|10|20|50|100] [-t] [-x] [url]\n",
                   appname);
-          exit(1);
+          return 1;
         case 'v':
         case 'V':
           fprintf(stderr, "\r%s %s - %s\n",
                   appname, CHKSPEED_VERSION, curl_version());
-          exit(1);
+          return 1;
         case 'a':
         case 'A':
           prtall = 1;
index 396aeca97e1845dd48dc276610e463bb282d833b..da40953d918a1b164789d9b4dfeee52bd782468e 100644 (file)
@@ -34,8 +34,7 @@
 #include <curl/curl.h>
 #include <curl/mprintf.h>
 
-static void
-print_cookies(CURL *curl)
+static int print_cookies(CURL *curl)
 {
   CURLcode res;
   struct curl_slist *cookies;
@@ -47,7 +46,7 @@ print_cookies(CURL *curl)
   if(res != CURLE_OK) {
     fprintf(stderr, "Curl curl_easy_getinfo failed: %s\n",
             curl_easy_strerror(res));
-    exit(1);
+    return 1;
   }
   nc = cookies;
   i = 1;
@@ -60,6 +59,8 @@ print_cookies(CURL *curl)
     printf("(none)\n");
   }
   curl_slist_free_all(cookies);
+
+  return 0;
 }
 
 int
index f8a463a7885e95a8052a840709dade579e557cd7..52dbdf1535b35761bc51359de1dec38ccb773432 100644 (file)
@@ -94,7 +94,7 @@ static bool init(CURL *&conn, const char *url)
 
   if(conn == NULL) {
     fprintf(stderr, "Failed to create CURL connection\n");
-    exit(EXIT_FAILURE);
+    return false;
   }
 
   code = curl_easy_setopt(conn, CURLOPT_ERRORBUFFER, errorBuffer);
@@ -270,7 +270,7 @@ int main(int argc, char *argv[])
 
   if(argc != 2) {
     fprintf(stderr, "Usage: %s <url>\n", argv[0]);
-    exit(EXIT_FAILURE);
+    return EXIT_FAILURE;
   }
 
   curl_global_init(CURL_GLOBAL_DEFAULT);
@@ -279,7 +279,7 @@ int main(int argc, char *argv[])
 
   if(!init(conn, argv[1])) {
     fprintf(stderr, "Connection initialization failed\n");
-    exit(EXIT_FAILURE);
+    return EXIT_FAILURE;
   }
 
   // Retrieve content for the URL
@@ -289,7 +289,7 @@ int main(int argc, char *argv[])
 
   if(code != CURLE_OK) {
     fprintf(stderr, "Failed to get '%s' [%s]\n", argv[1], errorBuffer);
-    exit(EXIT_FAILURE);
+    return EXIT_FAILURE;
   }
 
   // Parse the (assumed) HTML code
index 693f393ada034c4b39a35c331548781377f064f8..4a249fa97988f7aca61e6ef9a187126196470512 100644 (file)
@@ -142,7 +142,7 @@ int my_trace(CURL *handle, curl_infotype type,
   return 0;
 }
 
-static void setup(struct transfer *t, int num)
+static int setup(struct transfer *t, int num)
 {
   char filename[128];
   CURL *hnd;
@@ -155,7 +155,7 @@ static void setup(struct transfer *t, int num)
   if(!t->out) {
     fprintf(stderr, "error: could not open file %s for writing: %s\n",
             filename, strerror(errno));
-    exit(1);
+    return 1;
   }
 
   /* write to this file */
@@ -179,6 +179,7 @@ static void setup(struct transfer *t, int num)
   /* wait for pipe connection to confirm */
   curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L);
 #endif
+  return 0;
 }
 
 /*
@@ -204,7 +205,8 @@ int main(int argc, char **argv)
   multi_handle = curl_multi_init();
 
   for(i = 0; i < num_transfers; i++) {
-    setup(&trans[i], i);
+    if(setup(&trans[i], i))
+      return 1;
 
     /* add the individual transfer */
     curl_multi_add_handle(multi_handle, trans[i].easy);
index 88a1bdbabdcd968fa199f0892ae949bc0e72745a..580944f2710acad6adea291d7924c3a53003faf5 100644 (file)
@@ -200,7 +200,7 @@ static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
   return retcode;
 }
 
-static void setup(struct input *i, int num, const char *upload)
+static int setup(struct input *i, int num, const char *upload)
 {
   FILE *out;
   char url[256];
@@ -209,14 +209,15 @@ static void setup(struct input *i, int num, const char *upload)
   curl_off_t uploadsize;
   CURL *hnd;
 
-  hnd = i->hnd = curl_easy_init();
+  hnd = i->hnd = NULL;
+
   i->num = num;
   curl_msnprintf(filename, 128, "dl-%d", num);
   out = fopen(filename, "wb");
   if(!out) {
     fprintf(stderr, "error: could not open file %s for writing: %s\n", upload,
             strerror(errno));
-    exit(1);
+    return 1;
   }
 
   curl_msnprintf(url, 256, "https://localhost:8443/upload-%d", num);
@@ -225,7 +226,8 @@ static void setup(struct input *i, int num, const char *upload)
   if(stat(upload, &file_info)) {
     fprintf(stderr, "error: could not stat file %s: %s\n", upload,
             strerror(errno));
-    exit(1);
+    fclose(out);
+    return 1;
   }
 
   uploadsize = file_info.st_size;
@@ -234,9 +236,12 @@ static void setup(struct input *i, int num, const char *upload)
   if(!i->in) {
     fprintf(stderr, "error: could not open file %s for reading: %s\n", upload,
             strerror(errno));
-    exit(1);
+    fclose(out);
+    return 1;
   }
 
+  hnd = i->hnd = curl_easy_init();
+
   /* write to this file */
   curl_easy_setopt(hnd, CURLOPT_WRITEDATA, out);
 
@@ -269,6 +274,7 @@ static void setup(struct input *i, int num, const char *upload)
   /* wait for pipe connection to confirm */
   curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L);
 #endif
+  return 0;
 }
 
 /*
@@ -301,7 +307,8 @@ int main(int argc, char **argv)
   multi_handle = curl_multi_init();
 
   for(i = 0; i < num_transfers; i++) {
-    setup(&trans[i], i, filename);
+    if(setup(&trans[i], i, filename))
+      return 1;
 
     /* add the individual transfer */
     curl_multi_add_handle(multi_handle, trans[i].hnd);
index 6456c3e576befd78b8f3a0f2a5d0b434f3739c9b..cce8025e4d20275e45ab40b85549d754e0dd4f82 100644 (file)
@@ -482,7 +482,7 @@ AC_DEFUN([CURL_COMPILER_WORKS_IFELSE], [
         #endif
       ]],[[
         int i = 0;
-        exit(i);
+        return i;
       ]])
     ],[
       tmp_compiler_works="yes"
index 82bf39a3063088c3887c8652a52b243d25c875c6..fe55cb922af27bb5258555c0754bbdf253827f1c 100644 (file)
@@ -1270,11 +1270,12 @@ AC_DEFUN([CURL_CHECK_FUNC_GETADDRINFO], [
         struct addrinfo hints;
         struct addrinfo *ai = 0;
         int error;
+        int exitcode;
 
         #ifdef _WIN32
         WSADATA wsa;
         if(WSAStartup(MAKEWORD(2, 2), &wsa))
-          exit(2);
+          return 2;
         #endif
 
         memset(&hints, 0, sizeof(hints));
@@ -1283,9 +1284,15 @@ AC_DEFUN([CURL_CHECK_FUNC_GETADDRINFO], [
         hints.ai_socktype = SOCK_STREAM;
         error = getaddrinfo("127.0.0.1", 0, &hints, &ai);
         if(error || !ai)
-          exit(1); /* fail */
-        else
-          exit(0);
+          exitcode = 1; /* fail */
+        else {
+          freeaddrinfo(ai);
+          exitcode = 0;
+        }
+        #ifdef _WIN32
+        WSACleanup();
+        #endif
+        return exitcode;
       ]])
     ],[
       AC_MSG_RESULT([yes])
@@ -1883,9 +1890,11 @@ AC_DEFUN([CURL_CHECK_FUNC_GETIFADDRS], [
 
         error = getifaddrs(&ifa);
         if(error || !ifa)
-          exit(1); /* fail */
-        else
-          exit(0);
+          return 1; /* fail */
+        else {
+          freeifaddrs(ifa);
+          return 0;
+        }
       ]])
     ],[
       AC_MSG_RESULT([yes])
@@ -2003,9 +2012,9 @@ AC_DEFUN([CURL_CHECK_FUNC_GMTIME_R], [
         gmt = gmtime_r(&local, &result);
         (void)result;
         if(gmt)
-          exit(0);
+          return 0;
         else
-          exit(1);
+          return 1;
       ]])
     ],[
       AC_MSG_RESULT([yes])
@@ -2134,13 +2143,13 @@ AC_DEFUN([CURL_CHECK_FUNC_INET_NTOP], [
         /* - */
         ipv4ptr = inet_ntop(AF_INET, ipv4a, ipv4res, sizeof(ipv4res));
         if(!ipv4ptr)
-          exit(1); /* fail */
+          return 1; /* fail */
         if(ipv4ptr != ipv4res)
-          exit(1); /* fail */
+          return 1; /* fail */
         if(!ipv4ptr[0])
-          exit(1); /* fail */
+          return 1; /* fail */
         if(memcmp(ipv4res, "192.168.100.1", 13) != 0)
-          exit(1); /* fail */
+          return 1; /* fail */
         /* - */
         ipv6res[0] = '\0';
         memset(ipv6a, 0, sizeof(ipv6a));
@@ -2158,15 +2167,15 @@ AC_DEFUN([CURL_CHECK_FUNC_INET_NTOP], [
         /* - */
         ipv6ptr = inet_ntop(AF_INET6, ipv6a, ipv6res, sizeof(ipv6res));
         if(!ipv6ptr)
-          exit(1); /* fail */
+          return 1; /* fail */
         if(ipv6ptr != ipv6res)
-          exit(1); /* fail */
+          return 1; /* fail */
         if(!ipv6ptr[0])
-          exit(1); /* fail */
+          return 1; /* fail */
         if(memcmp(ipv6res, "fe80::214:4fff:fe0b:76c8", 24) != 0)
-          exit(1); /* fail */
+          return 1; /* fail */
         /* - */
-        exit(0);
+        return 0;
       ]])
     ],[
       AC_MSG_RESULT([yes])
@@ -2286,18 +2295,18 @@ AC_DEFUN([CURL_CHECK_FUNC_INET_PTON], [
         /* - */
         memset(ipv4a, 1, sizeof(ipv4a));
         if(1 != inet_pton(AF_INET, ipv4src, ipv4a))
-          exit(1); /* fail */
+          return 1; /* fail */
         /* - */
         if( (ipv4a[0] != 0xc0) ||
             (ipv4a[1] != 0xa8) ||
             (ipv4a[2] != 0x64) ||
             (ipv4a[3] != 0x01) ||
             (ipv4a[4] != 0x01) )
-          exit(1); /* fail */
+          return 1; /* fail */
         /* - */
         memset(ipv6a, 1, sizeof(ipv6a));
         if(1 != inet_pton(AF_INET6, ipv6src, ipv6a))
-          exit(1); /* fail */
+          return 1; /* fail */
         /* - */
         if( (ipv6a[0]  != 0xfe) ||
             (ipv6a[1]  != 0x80) ||
@@ -2310,7 +2319,7 @@ AC_DEFUN([CURL_CHECK_FUNC_INET_PTON], [
             (ipv6a[14] != 0x76) ||
             (ipv6a[15] != 0xc8) ||
             (ipv6a[16] != 0x01) )
-          exit(1); /* fail */
+          return 1; /* fail */
         /* - */
         if( (ipv6a[2]  != 0x0) ||
             (ipv6a[3]  != 0x0) ||
@@ -2318,9 +2327,9 @@ AC_DEFUN([CURL_CHECK_FUNC_INET_PTON], [
             (ipv6a[5]  != 0x0) ||
             (ipv6a[6]  != 0x0) ||
             (ipv6a[7]  != 0x0) )
-          exit(1); /* fail */
+          return 1; /* fail */
         /* - */
-        exit(0);
+        return 0;
       ]])
     ],[
       AC_MSG_RESULT([yes])
@@ -3809,11 +3818,11 @@ AC_DEFUN([CURL_CHECK_FUNC_STRERROR_R], [
         buffer[0] = '\0';
         string = strerror_r(EACCES, buffer, sizeof(buffer));
         if(!string)
-          exit(1); /* fail */
+          return 1; /* fail */
         if(!string[0])
-          exit(1); /* fail */
+          return 1; /* fail */
         else
-          exit(0);
+          return 0;
       ]])
     ],[
       AC_MSG_RESULT([yes])
@@ -3872,11 +3881,11 @@ AC_DEFUN([CURL_CHECK_FUNC_STRERROR_R], [
         buffer[0] = '\0';
         error = strerror_r(EACCES, buffer, sizeof(buffer));
         if(error)
-          exit(1); /* fail */
+          return 1; /* fail */
         if(buffer[0] == '\0')
-          exit(1); /* fail */
+          return 1; /* fail */
         else
-          exit(0);
+          return 0;
       ]])
     ],[
       AC_MSG_RESULT([yes])
index d08fe713b072ddd62c9f48246ec0d7af3e8cc74b..dd1713b244467ed89e3f75adf7bbbe61eb93fab3 100644 (file)
@@ -48,7 +48,7 @@ int main(int argc, char **argv)
 
   if(argc < 1) {
     puts("report_openssl_version filename");
-    exit(1);
+    return 1;
   }
 
   libptr = dlopen(argv[1], 0);
@@ -65,7 +65,7 @@ int main(int argc, char **argv)
 
   if(!ssl_version) {
     puts("Unable to lookup version of OpenSSL");
-    exit(1);
+    return 1;
   }
 
   version = ssl_version(SSLEAY_VERSION);
@@ -91,9 +91,9 @@ int main(int argc, char **argv)
 
     status = LIB$SET_SYMBOL(&symbol_dsc, &value_dsc, &table_type);
     if(!$VMS_STATUS_SUCCESS(status)) {
-      exit(status);
+      return status;
     }
   }
 
-  exit(0);
+  return 0;
 }
index 51d937ec315fbaccbb1ab3fbb2e88f5fe072ec64..9c6b88c37a8729ed2fc6a23ac676052e73943f3f 100644 (file)
@@ -140,12 +140,6 @@ static int debug_cb(CURL *handle, curl_infotype type,
   return 0;
 }
 
-#define ERR()                                                             \
-  do {                                                                    \
-    fprintf(stderr, "something unexpected went wrong - bailing out!\n");  \
-    exit(2);                                                              \
-  } while(0)
-
 static void usage(const char *msg)
 {
   if(msg)
@@ -196,6 +190,13 @@ static size_t cb(char *data, size_t size, size_t nmemb, void *clientp)
           handle->idx, (long)realsize);
   return realsize;
 }
+
+#define ERR()                                                             \
+  do {                                                                    \
+    fprintf(stderr, "something unexpected went wrong - bailing out!\n");  \
+    return 2;                                                             \
+  } while(0)
+
 #endif /* !_MSC_VER */
 
 int main(int argc, char *argv[])
@@ -254,19 +255,19 @@ int main(int argc, char *argv[])
   cu = curl_url();
   if(!cu) {
     fprintf(stderr, "out of memory\n");
-    exit(1);
+    return 1;
   }
   if(curl_url_set(cu, CURLUPART_URL, url, 0)) {
     fprintf(stderr, "not a URL: '%s'\n", url);
-    exit(1);
+    return 1;
   }
   if(curl_url_get(cu, CURLUPART_HOST, &host, 0)) {
     fprintf(stderr, "could not get host of '%s'\n", url);
-    exit(1);
+    return 1;
   }
   if(curl_url_get(cu, CURLUPART_PORT, &port, 0)) {
     fprintf(stderr, "could not get port of '%s'\n", url);
-    exit(1);
+    return 1;
   }
   memset(&resolve, 0, sizeof(resolve));
   curl_msnprintf(resolve_buf, sizeof(resolve_buf)-1, "%s:%s:127.0.0.1",
index 0cf939fc6461aa12a2ca4c312b147f26b8d8c6a5..751d674152af80a798af8b8f070dd822135b6275 100644 (file)
@@ -138,24 +138,25 @@ static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *opaque)
 int main(int argc, char *argv[])
 {
   const char *url;
-  CURLM *multi;
+  CURLM *multi = NULL;
   CURL *easy;
   CURLMcode mc;
   int running_handles = 0, start_count, numfds;
   CURLMsg *msg;
   int msgs_in_queue;
   char range[128];
+  int exitcode = 1;
 
   if(argc != 2) {
     fprintf(stderr, "%s URL\n", argv[0]);
-    exit(2);
+    return 2;
   }
 
   url = argv[1];
   multi = curl_multi_init();
   if(!multi) {
     fprintf(stderr, "curl_multi_init failed\n");
-    exit(1);
+    goto cleanup;
   }
 
   start_count = 200;
@@ -164,7 +165,7 @@ int main(int argc, char *argv[])
       easy = curl_easy_init();
       if(!easy) {
         fprintf(stderr, "curl_easy_init failed\n");
-        exit(1);
+        goto cleanup;
       }
       curl_easy_setopt(easy, CURLOPT_VERBOSE, 1L);
       curl_easy_setopt(easy, CURLOPT_DEBUGFUNCTION, debug_cb);
@@ -186,8 +187,9 @@ int main(int argc, char *argv[])
       mc = curl_multi_add_handle(multi, easy);
       if(mc != CURLM_OK) {
         fprintf(stderr, "curl_multi_add_handle: %s\n",
-               curl_multi_strerror(mc));
-        exit(1);
+                curl_multi_strerror(mc));
+        curl_easy_cleanup(easy);
+        goto cleanup;
       }
       --start_count;
     }
@@ -195,16 +197,16 @@ int main(int argc, char *argv[])
     mc = curl_multi_perform(multi, &running_handles);
     if(mc != CURLM_OK) {
       fprintf(stderr, "curl_multi_perform: %s\n",
-             curl_multi_strerror(mc));
-      exit(1);
+              curl_multi_strerror(mc));
+      goto cleanup;
     }
 
     if(running_handles) {
       mc = curl_multi_poll(multi, NULL, 0, 1000000, &numfds);
       if(mc != CURLM_OK) {
         fprintf(stderr, "curl_multi_poll: %s\n",
-               curl_multi_strerror(mc));
-        exit(1);
+                curl_multi_strerror(mc));
+        goto cleanup;
       }
     }
 
@@ -224,12 +226,12 @@ int main(int argc, char *argv[])
         else if(msg->data.result) {
           fprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T
                   ": failed with %d\n", xfer_id, msg->data.result);
-          exit(1);
+          goto cleanup;
         }
         else if(status != 206) {
           fprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T
                   ": wrong http status %ld (expected 206)\n", xfer_id, status);
-          exit(1);
+          goto cleanup;
         }
         curl_multi_remove_handle(multi, msg->easy_handle);
         curl_easy_cleanup(msg->easy_handle);
@@ -244,5 +246,22 @@ int main(int argc, char *argv[])
   } while(running_handles > 0 || start_count);
 
   fprintf(stderr, "exiting\n");
-  exit(EXIT_SUCCESS);
+  exitcode = EXIT_SUCCESS;
+
+cleanup:
+
+  if(multi) {
+    CURL **list = curl_multi_get_handles(multi);
+    if(list) {
+      int i;
+      for(i = 0; list[i]; i++) {
+        curl_multi_remove_handle(multi, list[i]);
+        curl_easy_cleanup(list[i]);
+      }
+      curl_free(list);
+    }
+    curl_multi_cleanup(multi);
+  }
+
+  return exitcode;
 }
index 9a63e779b32c1abbc0a3084e4a305a1febe72341..ef9d84a1310d4ba7192a482467a6c52c1051cd64 100644 (file)
@@ -136,9 +136,9 @@ static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *opaque)
   return size * nmemb;
 }
 
-static void add_transfer(CURLM *multi, CURLSH *share,
-                         struct curl_slist *resolve,
-                         const char *url, int http_version)
+static int add_transfer(CURLM *multi, CURLSH *share,
+                        struct curl_slist *resolve,
+                        const char *url, int http_version)
 {
   CURL *easy;
   CURLMcode mc;
@@ -146,7 +146,7 @@ static void add_transfer(CURLM *multi, CURLSH *share,
   easy = curl_easy_init();
   if(!easy) {
     fprintf(stderr, "curl_easy_init failed\n");
-    exit(1);
+    return 1;
   }
   curl_easy_setopt(easy, CURLOPT_VERBOSE, 1L);
   curl_easy_setopt(easy, CURLOPT_DEBUGFUNCTION, debug_cb);
@@ -167,30 +167,33 @@ static void add_transfer(CURLM *multi, CURLSH *share,
   mc = curl_multi_add_handle(multi, easy);
   if(mc != CURLM_OK) {
     fprintf(stderr, "curl_multi_add_handle: %s\n",
-           curl_multi_strerror(mc));
-    exit(1);
+            curl_multi_strerror(mc));
+    curl_easy_cleanup(easy);
+    return 1;
   }
+  return 0;
 }
 
 int main(int argc, char *argv[])
 {
   const char *url;
-  CURLM *multi;
+  CURLM *multi = NULL;
   CURLMcode mc;
   int running_handles = 0, numfds;
   CURLMsg *msg;
-  CURLSH *share;
+  CURLSH *share = NULL;
   CURLU *cu;
-  struct curl_slist resolve;
+  struct curl_slist *resolve = NULL;
   char resolve_buf[1024];
   int msgs_in_queue;
   int add_more, waits, ongoing = 0;
-  char *host, *port;
+  char *host = NULL, *port = NULL;
   int http_version = CURL_HTTP_VERSION_1_1;
+  int exitcode = 1;
 
   if(argc != 3) {
     fprintf(stderr, "%s proto URL\n", argv[0]);
-    exit(2);
+    return 2;
   }
 
   if(!strcmp("h2", argv[1]))
@@ -202,41 +205,41 @@ int main(int argc, char *argv[])
   cu = curl_url();
   if(!cu) {
     fprintf(stderr, "out of memory\n");
-    exit(1);
+    return 1;
   }
   if(curl_url_set(cu, CURLUPART_URL, url, 0)) {
     fprintf(stderr, "not a URL: '%s'\n", url);
-    exit(1);
+    goto cleanup;
   }
   if(curl_url_get(cu, CURLUPART_HOST, &host, 0)) {
     fprintf(stderr, "could not get host of '%s'\n", url);
-    exit(1);
+    goto cleanup;
   }
   if(curl_url_get(cu, CURLUPART_PORT, &port, 0)) {
     fprintf(stderr, "could not get port of '%s'\n", url);
-    exit(1);
+    goto cleanup;
   }
 
-  memset(&resolve, 0, sizeof(resolve));
   curl_msnprintf(resolve_buf, sizeof(resolve_buf)-1, "%s:%s:127.0.0.1",
                  host, port);
-  curl_slist_append(&resolve, resolve_buf);
+  resolve = curl_slist_append(resolve, resolve_buf);
 
   multi = curl_multi_init();
   if(!multi) {
     fprintf(stderr, "curl_multi_init failed\n");
-    exit(1);
+    goto cleanup;
   }
 
   share = curl_share_init();
   if(!share) {
     fprintf(stderr, "curl_share_init failed\n");
-    exit(1);
+    goto cleanup;
   }
   curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
 
 
-  add_transfer(multi, share, &resolve, url, http_version);
+  if(add_transfer(multi, share, resolve, url, http_version))
+    goto cleanup;
   ++ongoing;
   add_more = 6;
   waits = 3;
@@ -244,16 +247,16 @@ int main(int argc, char *argv[])
     mc = curl_multi_perform(multi, &running_handles);
     if(mc != CURLM_OK) {
       fprintf(stderr, "curl_multi_perform: %s\n",
-             curl_multi_strerror(mc));
-      exit(1);
+              curl_multi_strerror(mc));
+      goto cleanup;
     }
 
     if(running_handles) {
       mc = curl_multi_poll(multi, NULL, 0, 1000000, &numfds);
       if(mc != CURLM_OK) {
         fprintf(stderr, "curl_multi_poll: %s\n",
-               curl_multi_strerror(mc));
-        exit(1);
+                curl_multi_strerror(mc));
+        goto cleanup;
       }
     }
 
@@ -262,7 +265,8 @@ int main(int argc, char *argv[])
     }
     else {
       while(add_more) {
-        add_transfer(multi, share, &resolve, url, http_version);
+        if(add_transfer(multi, share, resolve, url, http_version))
+          goto cleanup;
         ++ongoing;
         --add_more;
       }
@@ -284,12 +288,12 @@ int main(int argc, char *argv[])
         else if(msg->data.result) {
           fprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T
                   ": failed with %d\n", xfer_id, msg->data.result);
-          exit(1);
+          goto cleanup;
         }
         else if(status != 200) {
           fprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T
                   ": wrong http status %ld (expected 200)\n", xfer_id, status);
-          exit(1);
+          goto cleanup;
         }
         curl_multi_remove_handle(multi, msg->easy_handle);
         curl_easy_cleanup(msg->easy_handle);
@@ -305,5 +309,27 @@ int main(int argc, char *argv[])
   } while(ongoing || add_more);
 
   fprintf(stderr, "exiting\n");
-  exit(EXIT_SUCCESS);
+  exitcode = EXIT_SUCCESS;
+
+cleanup:
+
+  if(multi) {
+    CURL **list = curl_multi_get_handles(multi);
+    if(list) {
+      int i;
+      for(i = 0; list[i]; i++) {
+        curl_multi_remove_handle(multi, list[i]);
+        curl_easy_cleanup(list[i]);
+      }
+      curl_free(list);
+    }
+    curl_multi_cleanup(multi);
+  }
+  curl_share_cleanup(share);
+  curl_slist_free_all(resolve);
+  curl_free(host);
+  curl_free(port);
+  curl_url_cleanup(cu);
+
+  return exitcode;
 }
index bd3d3eeea49417a6ed6fc42887771fce9c829690..a9a439bf6bb15a0ea5d0bb0f29694e5d34d9a512 100644 (file)
@@ -180,12 +180,6 @@ static int progress_callback(void *clientp,
   return 0;
 }
 
-#define ERR()                                                             \
-  do {                                                                    \
-    fprintf(stderr, "something unexpected went wrong - bailing out!\n");  \
-    exit(2);                                                              \
-  } while(0)
-
 static void usage(const char *msg)
 {
   if(msg)
@@ -196,6 +190,13 @@ static void usage(const char *msg)
     "  -V http_version (http/1.1, h2, h3) http version to use\n"
   );
 }
+
+#define ERR()                                                             \
+  do {                                                                    \
+    fprintf(stderr, "something unexpected went wrong - bailing out!\n");  \
+    return 2;                                                             \
+  } while(0)
+
 #endif /* !_MSC_VER */
 
 int main(int argc, char *argv[])
@@ -245,19 +246,19 @@ int main(int argc, char *argv[])
   cu = curl_url();
   if(!cu) {
     fprintf(stderr, "out of memory\n");
-    exit(1);
+    return 1;
   }
   if(curl_url_set(cu, CURLUPART_URL, url, 0)) {
     fprintf(stderr, "not a URL: '%s'\n", url);
-    exit(1);
+    return 1;
   }
   if(curl_url_get(cu, CURLUPART_HOST, &host, 0)) {
     fprintf(stderr, "could not get host of '%s'\n", url);
-    exit(1);
+    return 1;
   }
   if(curl_url_get(cu, CURLUPART_PORT, &port, 0)) {
     fprintf(stderr, "could not get port of '%s'\n", url);
-    exit(1);
+    return 1;
   }
   memset(&resolve, 0, sizeof(resolve));
   curl_msnprintf(resolve_buf, sizeof(resolve_buf)-1, "%s:%s:127.0.0.1",
@@ -267,7 +268,7 @@ int main(int argc, char *argv[])
   curl = curl_easy_init();
   if(!curl) {
     fprintf(stderr, "out of memory\n");
-    exit(1);
+    return 1;
   }
   /* We want to use our own read function. */
   curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
index 7070a4f688d96e3ca3f1a9619ee13ae527fed542..2fc3a5f94a891442e49817777bc36effaddd39e8 100644 (file)
@@ -1018,8 +1018,8 @@ int main(int argc, char *argv[])
             logdir, SERVERLOGS_LOCKDIR, ipv_inuse);
 
 #ifdef _WIN32
-  win32_init();
-  atexit(win32_cleanup);
+  if(win32_init())
+    return 2;
 #endif
 
   CURL_SET_BINMODE(stdin);
index b09d50368f65d699a7a62616d1674637e0bf0ff9..56964e03a93df48a9a71cb6e32e9a4ca2f5c2614 100644 (file)
@@ -99,8 +99,8 @@ int main(int argc, char *argv[])
   }
 
 #ifdef _WIN32
-  win32_init();
-  atexit(win32_cleanup);
+  if(win32_init())
+    return 2;
 #endif
 
 #if defined(CURLRES_IPV6)
index d3acefc0daff7f39b8571facecc48d52b1a30d19..181568395fbd26ba1243205df6870090ab8ef37f 100644 (file)
@@ -1145,8 +1145,8 @@ int main(int argc, char *argv[])
             logdir, SERVERLOGS_LOCKDIR, ipv_inuse);
 
 #ifdef _WIN32
-  win32_init();
-  atexit(win32_cleanup);
+  if(win32_init())
+    return 2;
 #endif
 
   install_signal_handlers(false);
index e164f5f2a5e4760dd2452b8b75847da4cb63a169..18f75a52367c79b019fb215f07d41aeb28019250 100644 (file)
@@ -1507,8 +1507,8 @@ int main(int argc, char *argv[])
   }
 
 #ifdef _WIN32
-  win32_init();
-  atexit(win32_cleanup);
+  if(win32_init())
+    return 2;
 #endif
 
   CURL_SET_BINMODE(stdin);
index f63ffdb51b64ed2dcbe7340ff0fabc57dcccf396..92b261454e42bca2c99f4a864c5a4fb5be5ffc1a 100644 (file)
@@ -1086,8 +1086,8 @@ int main(int argc, char *argv[])
   }
 
 #ifdef _WIN32
-  win32_init();
-  atexit(win32_cleanup);
+  if(win32_init())
+    return 2;
 #endif
 
   CURL_SET_BINMODE(stdin);
index c42bfe90b5e68f5c4c17c79b406eef9a46b6325d..fa83bc6a9a6f6a45a2345add55c4a06252bbcb1d 100644 (file)
@@ -1611,7 +1611,7 @@ static void http_connect(curl_socket_t *infdp,
           if(!req2) {
             req2 = malloc(sizeof(*req2));
             if(!req2)
-              exit(1);
+              goto http_connect_cleanup;  /* fail */
           }
           memset(req2, 0, sizeof(*req2));
           logmsg("====> Client connect DATA");
@@ -2207,8 +2207,8 @@ int main(int argc, char *argv[])
             is_proxy ? "-proxy" : "", socket_type);
 
 #ifdef _WIN32
-  win32_init();
-  atexit(win32_cleanup);
+  if(win32_init())
+    return 2;
 #endif
 
   install_signal_handlers(false);
index c296f7e20fe4ce6b3b13b9ed1cdf10f88a9063b8..93f6537c6d04c28c548dde4c3e83b4a1fb3643c9 100644 (file)
@@ -644,8 +644,8 @@ int main(int argc, char **argv)
             logdir, SERVERLOGS_LOCKDIR, ipv_inuse);
 
 #ifdef _WIN32
-  win32_init();
-  atexit(win32_cleanup);
+  if(win32_init())
+    return 2;
 #endif
 
   install_signal_handlers(true);
index 42a4f857e850f5674a8b6a64a3b1699e20f9144d..d9f6d2162a5c72d4a971ea00cc7a8e7891705eb5 100644 (file)
@@ -153,7 +153,17 @@ void win32_perror(const char *msg)
   fprintf(stderr, "%s\n", buf);
 }
 
-void win32_init(void)
+static void win32_cleanup(void)
+{
+#ifdef USE_WINSOCK
+  WSACleanup();
+#endif  /* USE_WINSOCK */
+
+  /* flush buffers of all streams regardless of their mode */
+  _flushall();
+}
+
+int win32_init(void)
 {
 #ifdef USE_WINSOCK
   WORD wVersionRequested;
@@ -166,7 +176,7 @@ void win32_init(void)
   if(err) {
     perror("Winsock init failed");
     logmsg("Error initialising Winsock -- aborting");
-    exit(1);
+    return 1;
   }
 
   if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
@@ -174,19 +184,11 @@ void win32_init(void)
     WSACleanup();
     perror("Winsock init failed");
     logmsg("No suitable winsock.dll found -- aborting");
-    exit(1);
+    return 1;
   }
 #endif  /* USE_WINSOCK */
-}
-
-void win32_cleanup(void)
-{
-#ifdef USE_WINSOCK
-  WSACleanup();
-#endif  /* USE_WINSOCK */
-
-  /* flush buffers of all streams regardless of their mode */
-  _flushall();
+  atexit(win32_cleanup);
+  return 0;
 }
 
 /* socket-safe strerror (works on Winsock errors, too) */
index b225478ff94e7de922c69f58f901ef8537e5aac6..991c0703ce71e1fbdc4747f12fb2fe4f941ca7e3 100644 (file)
@@ -51,8 +51,7 @@ extern const char *cmdfile;
 #define perror(m) win32_perror(m)
 void win32_perror(const char *msg);
 
-void win32_init(void);
-void win32_cleanup(void);
+int win32_init(void);
 const char *sstrerror(int err);
 #else   /* _WIN32 */